PDA

View Full Version : سوال: نحوه بایند کردن رنگ فونت در DataGridTextColumn



elec60
شنبه 16 اسفند 1393, 21:38 عصر
سلام

وقتی که Foreground مربوط به DataGridTextColumn رو در XAML ست میکنم اعمال میشه ولی وقتی همین خاصیت رو بایند میکنم به یه پارامتر bool و از یه Converter استفاده میکنم و تو این کانورتر اگه پارامتر true بود یه رنگ و اگه false بود یه رنگ دیگه بر می گردونم به خاصیت Forground اعمال نمیشه!

چطور میشه این کار رو انجام بدم؟

یه موردی هست که باعث شده یکم از اومدن به این سایت دلسرد بشم اونم اینه که به هیچ کدوم از سوالاتم پاسخ درستی داده نشده!

SabaSabouhi
یک شنبه 17 اسفند 1393, 08:21 صبح
سلام

وقتی که Foreground مربوط به DataGridTextColumn رو در XAML ست میکنم اعمال میشه ولی وقتی همین خاصیت رو بایند میکنم به یه پارامتر bool و از یه Converter استفاده میکنم و تو این کانورتر اگه پارامتر true بود یه رنگ و اگه false بود یه رنگ دیگه بر می گردونم به خاصیت Forground اعمال نمیشه!

چطور میشه این کار رو انجام بدم؟

یه موردی هست که باعث شده یکم از اومدن به این سایت دلسرد بشم اونم اینه که به هیچ کدوم از سوالاتم پاسخ درستی داده نشده!

سلام
1. گمان کنم باید binding رو توی template انجام بدی، نه مستقیم.
2. دو تا دلیل داره، یکی این که خیلی کم هستن مشتریان WPF ( متاسفانه ) و دیگه این که کسانی هم که WPF کار می‌کنن به دلایل زیاد، تمام گوشه‌ و کنار
WPF رو نگشتن. خود من خیلی چیزها هست که نمی‌دونم. ( مثلاً Blend اصلا کار نکردم )

اگه کسی پرسشی داشته باشه که من تجربه کرده باشم، حتماً جواب می‌دم. دیگران هم همینطور.
خوش‌بختانه اینجا کسی «خسیس» نیست و تا جایی که من دیدم، همه دوستان تا حدی که دانش دارن، اون رو به دوستان ارائه می‌دن.

صبا صبوحی

SabaSabouhi
یک شنبه 17 اسفند 1393, 08:28 صبح
سلام
ببخشید، پست قبلی رو که ارسال کردم، بعدش به فکر افتادم که یه چیزهایی بهش اضافه کنم. اما تصمیم گرفتم تو یه پست جداگانه باشه.
Binding تو WPF مبحث خیلی گسترده و پیچیده‌ای داره. و نیمی از قدرت فوق‌العاده زیاد این محیط مربوط به همین Binding قدرتمند هست.
یکی از قسمت‌هایی که هنوز توش یه مقدار مشکل دارم ( هر چند که کارم رو راه می‌اندازم )، Template-Binding هست.
شما باید برای اون بخشی که می‌خوای رنگ یا تنظیمات دیگه‌ای براش Set کنی Template بسازی و اونجا کار Binding رو انجام بدی.
و بجای Binding از Templatebinding استفاده کنی.
این دو تا لینک رو حتماً مطالعه کن:
https://msdn.microsoft.com/en-us/library/ms752347(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/ms742521(v=vs.110).aspx

صبا صبوحی

elec60
یک شنبه 17 اسفند 1393, 22:40 عصر
بله کاملا درسته، تو Stackoverflow همواره جوابی برای سوالاتم پیدا میکنم و راه حلش رو اونجا هم همین Template Binding گفتن، اما میخواستم دلیل فنی این مورد رو بدونم که چرا با بایندینگ مستقیم عمل نمیکنه.

لینکهایی که دادین قبلا مطالعه کردم و خیلی عالی بودن، البته فکر میکنم کتاب Adam Nathan هم خیلی مرجع خوب و کاملی برای WPF هست. بنده هم با اینکه خیلی رو WPF وقت گذاشتم اما همچنان اول راهم. با همین دانش اندکی از WPF که دارم کارهایی انجام دادم که صد سال دیگه با سایر تکنولوژیها نمیتونم، حالا در عجبم که چر تعداد علاقمندان به تکنولوژی منسوخ(از نظر من) WinForms خیلی بیشتره و چرا اصلا مایکروسافت رهاش نمیکنه و لااقل بیخیال توسعه بیشترش نمیشه!

elec60
یک شنبه 17 اسفند 1393, 22:52 عصر
تو بحث Binding یه سوال داشتم گفتم تاپیک جداگانه ای ایجاد نکنم.

یه ObservableColletion دارم که کلاسهایی از نوع People رو نگهداری میکنه و هر وقت یه شی از این تایپ از مجموعه حذف میشه و یا یک شی جدید اضافه میشه یه Notify به یک DataGrid ای که بهش بایند شده انجام میده و DataGrid تغییرات رو اعمال میکنه. ولی وقتی که یکی از اعضا این مجموعه Modify میشه(مثلا یکی از فیلدهاش تغییر میکنه) DataGrid رو notify نمیکنه که البته طبیعی به نظر میرسه، من مجبور میشم هر دفعه که فیلدی از People تغییر کردPeople رو از مجموعه حذف کنم و دوباره Insert کنم تا Notify کنه اما راه حل منطقی به نظر نمیاد!

SabaSabouhi
دوشنبه 18 اسفند 1393, 13:39 عصر
بله کاملا درسته، تو Stackoverflow همواره جوابی برای سوالاتم پیدا میکنم و راه حلش رو اونجا هم همین Template Binding گفتن، اما میخواستم دلیل فنی این مورد رو بدونم که چرا با بایندینگ مستقیم عمل نمیکنه.

لینکهایی که دادین قبلا مطالعه کردم و خیلی عالی بودن، البته فکر میکنم کتاب Adam Nathan هم خیلی مرجع خوب و کاملی برای WPF هست. بنده هم با اینکه خیلی رو WPF وقت گذاشتم اما همچنان اول راهم. با همین دانش اندکی از WPF که دارم کارهایی انجام دادم که صد سال دیگه با سایر تکنولوژیها نمیتونم، حالا در عجبم که چر تعداد علاقمندان به تکنولوژی منسوخ(از نظر من) WinForms خیلی بیشتره و چرا اصلا مایکروسافت رهاش نمیکنه و لااقل بیخیال توسعه بیشترش نمیشه!

سلام
برای این که وقتی داری دیتاگرید کار می‌کنی، واقعاً ستونی وجود نداره، این ستونها ( و سلول‌ها ) هنگام نمایش از روی یه Template ساخته می‌شن، به همین دلیل باید تو Template تنظیمات
رو انجام بدی.

صبا صبوحی

SabaSabouhi
دوشنبه 18 اسفند 1393, 13:44 عصر
تو بحث Binding یه سوال داشتم گفتم تاپیک جداگانه ای ایجاد نکنم.

یه ObservableColletion دارم که کلاسهایی از نوع People رو نگهداری میکنه و هر وقت یه شی از این تایپ از مجموعه حذف میشه و یا یک شی جدید اضافه میشه یه Notify به یک DataGrid ای که بهش بایند شده انجام میده و DataGrid تغییرات رو اعمال میکنه. ولی وقتی که یکی از اعضا این مجموعه Modify میشه(مثلا یکی از فیلدهاش تغییر میکنه) DataGrid رو notify نمیکنه که البته طبیعی به نظر میرسه، من مجبور میشم هر دفعه که فیلدی از People تغییر کردPeople رو از مجموعه حذف کنم و دوباره Insert کنم تا Notify کنه اما راه حل منطقی به نظر نمیاد!

سلام
طبیعی هست. برای این که ObservableCollection فقط تغییر در فهرست رو اعلام می‌کنه. با ویرایش یه رکورد، اون فهرست تغییری نمی‌کنه.
اما راه حل شما کاملاً نادرسته. راه درستش اینه:
1. کلاس People باید INotifyPropertyChanged رو Implement کنه.
2. برای کلیه Propertyهایی که تغییرشون قراره نمایش داده بشه باید به این شکل عمل کنی:


private string _name;
public string Name{
get { return _name; }
set {
if ( _name == value ) return;
_name = value;
OnPropertyChanged( this, "Name" );
}
}

به همین راحتی.
البته شاید حیلی راحت هم نباشه که برای تمام Propertyها این رو درست کنی، من که خودم این قسمت کد رو با CodeGenerator
ایجاد می‌کنم و مثل بنز هم داره کار می‌کنه.
ضمن این که مشکل به روز شدن DataGrid حل می‌شه، 1001 جای دیگه هم می‌تونی از این PropertyChanged استفاده کنی. مثل
کنترل دستی سایر مقادیر. یا مثل همون مشکلی که تو این سایت حداقل N بار دیدم. «وقتی مقدار یک Combo رو عوض می‌کنم می‌خوام ItemsSource
یه Comboی دیگه هم عوض بشه.» دقیقاً جای انجامش همین جا هست.

صبا صبوحی
صبا صبوحی

elec60
دوشنبه 18 اسفند 1393, 18:31 عصر
بله کاملا راه حل درستی هست، از این راه حل قبلا استفاده کردم، مشکل اینجاست که تعداد پراپرتی هام خیلی زیاد هست(هر کلاس تا ۳۰ تا و بعضا تا ۵۰ تا) و خیلی درد سر داره اگه بخوام واسه کلش کد بنویسم. مخصوصا اینکه این کلاسها رو EF تولید میکنه و بعضا مجبور میشم تو دیزاینرش Property اضافه کنم یا تغییراتی بدم که دیزاینر دوباره کلاسها رو از نو تولید میکنه و کلی کار گل دیگه هم باید دوباره انجام بدم.

یه راه حلی هم به ذهنم رسیده گفتم شاید بشه یه ObservableCollectionEX از یک ObservableCollection به ارث برد و طوری پیاده سازیش کرد که با تغییرات هر خاصیت از اعضای مجموعه عمل Notification انجام بشه اما هنوز روش کار نکردم.

یه سرچ تو Stackoverflow زدم و این کار رو یکی انجام داده اما یکی از متدهاشو پیاده سازی نکرده ببینید میتونین کمک کنید کاملش کنیم:


public class ChangeTrackerCollection<T> : ObservableCollection<T>
{
protected override void ClearItems()
{
foreach (var item in this)
UnregisterItemEvents(item);

base.ClearItems();
}

protected override void InsertItem(int index, T item)
{
base.InsertItem(index, item);

RegisterItemEvents(item);
}

protected override void RemoveItem(int index)
{
UnregisterItemEvents(this[index]);

base.RemoveItem(index);
}

private void RegisterItemEvents(T item)
{
item.PropertyChanged += this.OnItemPropertyChanged;
}

private void UnregisterItemEvents(T item)
{
item.PropertyChanged -= this.OnItemPropertyChanged;
}

private void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
//TODO: raise event to parent object to notify that there was a change...
}
}

elec60
دوشنبه 18 اسفند 1393, 18:35 عصر
سلام
برای این که وقتی داری دیتاگرید کار می‌کنی، واقعاً ستونی وجود نداره، این ستونها ( و سلول‌ها ) هنگام نمایش از روی یه Template ساخته می‌شن، به همین دلیل باید تو Template تنظیمات
رو انجام بدی.

صبا صبوحی

درسته، اما فکر کردم وقتی که میشه مثلا Foreground یه ستون رو قبل از تولید شدنس به مثلا یه رنگ ست کرد چرا نباید بشه همین خاصیت رو بایند کرد!؟

SabaSabouhi
سه شنبه 19 اسفند 1393, 01:24 صبح
سلام
دوست عزیز، متن شما خوانا نبود. لطفاً قبل از paste در تالار، متن رو توی NotePad کپی کنید و بعد دوباره عمل copy-paste رو انجام بدین. ( این روش ابتکار خودم بود برای نجات از این Scriptهای رنگ )
ضمن این که حق با شماست، و به صورت دستی مشکل زیاد هست. اما روش‌های مکانیزه هم برای این کار وجود داره.
مثلاً روشی که من استفاده نمی‌کنم اینه که شما می‌تونی کد T4 که EF کدهای مربوط به کلاس جدول‌ها رو از روش درست می‌کنه قابل ویرایش هست.
این صرفاً سرنخ بود. بیشتر نپرس که نمی‌دونم. ( مطلب به نقل از یکی از دوستانم که در این زمینه کار کرده بود )

صبا صبوحی