سلامی مجدد استاد .
خیلی ممنون
نکات برای یادآوری آینده :
این نکته را برای خودم در آینده برای یادآوری میگم .
قضیه اینه که قبلا کلاس ItemsControlCustomItem را نوشته بودم (که خود این هم داستان داشت و پیشنهاد داده بودین که بجای استفاده از کلاس هایی مثل ComboBoxItem ، ازش استفاده کنم) . و به عنوان آیتم ، در کنترل هایی مثل ComboBox (و کلا ItemsControl ها) ازش استفاده میکردم .
برای این کلاس هم ، اینترفیس INotifyPropertyChanged را برای استفاده و فراخونی در پروپرتی هاش بکار بردم .
تا اینجای کار ، مشکلی نبود و درست کار میکرد .
- اما بعد گفتم که حالا اگه یه وقتی اومد که پروپرتی های ItemsControlCustomItem را خواستم به عنوان Binding Target استفاده کنم ، پس بهتره که پروپرتی هاش را DependencyProperty و در نتیجه ، خودِ ItemsControlCustomItem را هم از DependencyObject ارث بری کنم .
- این کار را که انجام دادم ، دیدم وقتی آیتمی را که از لیست کمبوباکس ام انتخاب میکنم (کمبوباکس ای که مقدار آیتم هاش و در واقع ItemsSource اش از نوع ItemsControlCustomItem هست) ، در قسمت بالا اش (یا همون در قسمت ToggleButton یا Editable اش) نمایش داده نمیشه . هر چند در قسمت لیست ها (یا همون قسمت popup) ، آیتم هاش نمایش داده میشن .
مثل تصویر زیر :
با اونکه آیتم اول (متن درایو c) قبلا انتخاب شده بود ، اما در قسمت بالای کمبوباکس نمایش داده نمیشه .
بعد رفتم بررسی که کردم ، دیدم توی تمپلیت ای که بکار بردم (از مایکروسافت که گرفته بودم) ، ContentPresenter ای (با نام ContentSite) گرفته بود که پروپرتیِ Content اش را به پروپرتیِ SelectionBoxItem ئه ComboBox متصل و Binding کرده بود . که مربوط به نمایش محتوا در همین ToggleButton (قسمت بالای کمبوباکس) میشه .
در Visual Studio 2022 هم اومدن هر کلاسی که نوشتن ، با تمام اعضاشون (حتی اعضای private) را حتی با سورس کد کامل در اختیارمون گذاشتن (دیگه لازم نیست با نرم افزارهای دیگه ، سورس کد را جستجو کنیم) .
عبارت "SelectionBoxItem" را جستجو کردم ، خود پروپرتی اش کد خاصی نداشت اما به متد UpdateSelectionBoxItem برخوردم .
دیدم آخر این متد ، مقدار متغییر محلیِ obj را درون پروپرتیِ SelectionBoxItem سِت میکنه .
در ابتدا که این متغییر محلیِ obj ، مقدارش را از پروپرتیِ base.InternalSelectedItem میگرفت . مقدار این پروپرتی را با ربفلکشن برای شیِ کمبوباکس ام تست کردم :
C#:
private void SelectDriveComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBox currentComboBox = sender as ComboBox;
System.Reflection.BindingFlags bindingFlags = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic;
System.Reflection.PropertyInfo propertyInfo = currentComboBox.GetType().GetProperty("InternalSelectedItem", bindingFlags);
object val = propertyInfo.GetValue(currentComboBox);
}
دیدم مقدارش درسته (همون مقداری هست که اون آیتم را انتخاب کرده بودم . یعنی شی ای از ItemsControlCustomItem هست) .
در ادامه ی اون متد دیدم که شرط هایی میذاره و مقادیر متغییر محلی obj را تغییر میده .
==========================
- در نهایت (در این متد و همچنین در متد ExtractString که از این متد ، در شرایطی فراخونی میشد) ، شرط هایی گذاشت که خلاصه اش اینه که
اگه متغییر محلی obj (همون
آیتم انتخاب شده مون) ،
از نوع Visual (و فرزندانش مثل ContentControl و UIElement و TextBlock)
و TextElement بود ، محتوای مورد نظر را بسته به هر نوعی از اینها ، از پروپرتیِ خاصی از اینها یا به همراه فرمول خاصی ، بگیره اما اگه از نوع اینها
نبود (
یعنی فقط از نوع DependencyObject بود ، که شیِ ItemsControlCustomItem ما هم فقط از نوع DependencyObject هست) ،
و همچنین اگه یکی از پروپرتی های ItemTemplate یا ItemTemplateSelector یا ItemStringFormat (از اعضای ItemsControl) هم مقدار نداشت ، متد ExtractString را فراخونی میکنه که این متد هم با این شرایط ، مقدار اولیه اش که
رشته ی خالی هست را برمیگردونه و نهایتا از این رشته ی خالیِ برگردونده شده ، در متغییر محلیِ obj و در نهایت ، این متغییر محلی را هم
در پروپرتیِ SelectionBoxItem سِت و تنظیم میکنه .
-
بنابراین با مقداردهیِ یکی از این پروپرتی های ItemsControl (
فرضا پروپرتیِ ItemTemplate که تمپلیتِ آیتم های ItemsControl را مشخص میکنه) ،
این مشکل حل میشه .
در این کمبوباکس ام ، پروپرتیِ ItemTemplate را بصورت زیر نوشتم :
XML:
<DataTemplate DataType="{x:Type CustomItems:ItemsControlCustomItem}" x:Key="ItemsControlCustomItem_DataTemplateKey" >
<TextBlock Text="{Binding Path=ItemContent}"/>
</DataTemplate>
البته ، خلاصه ی اون متد و این داستان این بود .
============================
استاد ، در Visual Studio 2022 ، هم سورس کدها و هم همه ی اعضای (حتی اعضای private) اون کلاس هایی که مایکروسافت نوشت ، قابل مشاهده هست .
البته من نمیدونم بخاطرِ نسخه ی Visual Studio 2022 اش هست یا اینکه من موقع نصب ، گزینه ای را انتخاب کردم که این ویژگی اضافه شده .
به هر حال خوبی اش اینه که دیباگ گیری (از طریق مشاهده ی کامل کد) را آسونتر میکنه اما بدیش اینه که چون همه ی اعضا مشخص هست ، خیلی شلوغ تر از قبل شده .
آیا توی تنظیمات ، گزینه ای هست که هر وقت خواستیم ، این ویژگی را فعال یا غیر فعال کنیم؟
--------
همچنین اینکه در این نسخه ، در کد سی شارپ ، در intellisense ، وقتی کد مینویسم ، توضیحات اعضاها را نمیاره .
اون اعضا ، توضیحات xaml دارن (توی نسخه های قبلی میاورد) .
چرا؟ میشه درستش کرد؟ اگه آره ، چجوری؟
تشکر استاد