سئوالات و مباحث WPF

the_king

مدیرکل انجمن
اما دلیلش را متوجه نشدم که چطور شد که با مقدار جدید دادن به پروپرتی های ViewModel ، این مشکل هم حل شد؟
من بخشی از کدهای پروژه را که فکر میکنم به این مشکل شاید مربوط باشه را جوری که خلاصه هم بشه ، در پست بعدی (پست زیر) میذارم .
یک مجموعه از ComboBoxItem ها تشکیل شده که علاوه بر نگهداری رشته خروجی DriveInfoFormatted هر رفتاری که در ComboBox در مورد اون آیتم انجام میشه، فرضا انتخاب شدن آیتم رو (IsSelected) حفظ می کنه. ComboBox تغییرات رو روی این ComboBoxItem اعمال کرده و شما هم حفظ اش کردید. اگر همچین مجموعه ای حفظ بشه، در دفعات بعدی ComboBox نتیجه فعالیت قبلی رو بخاطر داره و همون رو نشون میده.

در نسخه اولیه شما یک مجموعه ComboBoxItem رو مشترکا برای همه ComboBox ها بکار می بردید، در نتیجه منبع اشتراکی داشتند و هر ComboBox ای رو که نشون می دادید همان آیتمی رو انتخاب کرده بود که در آخرین ComboBox انتخاب شده.
در ویرایش بعدی شما منبع ComboBox ها رو از هم تفکیک شون کردید ولی حالا همچنان یک مجموعه ComboBoxItem رو برای دفعات بعدی اجرای یک ComboBox حفظ می کنید و در نتیجه انتخاب قبلی ComboBox هم حفظ میشه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
یک مجموعه از ComboBoxItem ها تشکیل شده که علاوه بر نگهداری رشته خروجی DriveInfoFormatted هر رفتاری که در ComboBox در مورد اون آیتم انجام میشه، فرضا انتخاب شدن آیتم رو (IsSelected) حفظ می کنه. ComboBox تغییرات رو روی این ComboBoxItem اعمال کرده و شما هم حفظ اش کردید. اگر همچین مجموعه ای حفظ بشه، در دفعات بعدی ComboBox نتیجه فعالیت قبلی رو بخاطر داره و همون رو نشون میده.

خیلی ممنون استاد .
نه .
وقتی که آیتم های کمبوباکس را Binding نکنم و از متد برای پر کردن آیتم های کمبوباکس استفاده کنم (در این صورت ، حتی در هر جا که پروپرتیِ مربوط به ViewModel و همچنین پروپرتیِ UI وجود داشته باشه ، اگه از شیِ واحدی برای این پروپرتی ها استفاده کنم) ، این مشکل وجود نخواهد داشت .


یعنی اگه در پست قبلی ، در متد سازنده ی SettingWindow (کد دوم) ، شیِ جدیدی هم به پروپرتی های VssBackupViewModel و ExtensionMethodViewModel و UI ندم و همچنین برای کمبوباکس ، از Binding استفاده نکنم و همچنین متدِ SetFixedDriveComboBoxItemsProperty را بصورت زیر تغییر بدم (بجای ست کردنِ مقدار به پروپرتی در این متد ، مستقیما مقادیر مورد نظر درون کمبوباکس بریزم) ، این مشکل حل میشه و درست کار میکنه :

C#:
        public void SetFixedDriveComboBoxItemsProperty(ComboBox comboBox)
        {
            DriveInfo[] driveInfos = ExtensionMethodViewModel.GetFixedNtfsDrives();
            if (driveInfos == null || driveInfos.Length < 1)
                return;

            this.FixedDriveComboBoxItems = new List<ComboBoxItem>();
            foreach (DriveInfo driveInfo in driveInfos)
            {
                this.ExtensionMethodViewModel.DriveInfoObjectForExtensionMethod = driveInfo;
                string driveInfoFormatted = this.ExtensionMethodViewModel.DriveInfoFormatted();
                
                ComboBoxItem comboBoxItem = new ComboBoxItem();
                comboBoxItem.Content = driveInfoFormatted;
                comboBoxItem.Tag = driveInfo;
                
                comboBox.Items.Add(comboBoxItem);
            }

این متد ، در رویداد Load ئه Window ئه مربوطه (فرضا SettingWindow) ، فراخونی میشه .
و هیچ مشکلی هم با استفاده از یک شیِ واحد برای پروپرتیِ ExtensionMethodViewModel نداره .


ببینید ، اون مشکلی که بخاطر استفاده از یه شیِ واحد که برای پروپرتیِ UI استفاده میکردم (و سورسِ کمبوباکس ها را به یه شیِ واحد از پروپرتیِ FixedDriveComboBoxItems ئه PoshtibangirToloUI متصل کرده بودم) را درک میکنم برای چی بود .
چون از یه شیِ واحد از PoshtibangirToloUI و بنابراین از یه شیِ واحد برای پروپرتیِ FixedDriveComboBoxItems استفاده میشد ، بنابراین یه شیِ واحدِ CollectionView برای هر دو کمبوباکس در نظر گرفته میشه که باعث میشد وقتی در یه کمبوباکس ، یه گزینه را انتخاب کنیم ، در کمبوباکسِ دیگه ، همون گزینه ، انتخاب شده باشه .

--------------------

اما متوجه نشدم که چطور شد که (وقتی که از Binding و کد قبلی که در پست قبلی دادم ، استفاده میکنم) ، وقتی شیِ جدیدی برای پروپرتیِ ExtensionMethodViewModel در نظر میگیرم (با توجه به اینکه این پروپرتی ، در متدِ SetFixedDriveComboBoxItemsProperty استفاده و فراخونی شده) ، مشکل حل میشه . (منظورم متد SetFixedDriveComboBoxItemsProperty در کد پست قبلی هست که اون کد برای Binding استفاده شده) .

اما وقتی که از Binding استفاده نمیکنم ، یعنی وقتی که مستقیما در متد ، آیتم های کمبوباکس را پر میکنم ، یعنی وقتی که از متدِ SetFixedDriveComboBoxItemsProperty ای که در خط بالا (همین پست) دادم ، استفاده میکنم ، هیچ مشکلی نداره .
با اونکه در این متد (در خط بالا در همین پست) ، هم از پروپرتیِ ExtensionMethodViewModel استفاده کردم و هم مقدارِ جدیدی براش در نظر نگرفتم .

فرقِ این دو متد در این دو پست (پست فعلی و قبلی) چیه که در یکی (در پست قبلی که کد برای استفاده در Binding هست) ، باید شیِ جدیدی برای پروپرتیِ ExtensionMethodViewModel در نظر بگیرم تا درست کار کنه اما برای همین پروپرتی در همین کد ، وقتی برای Binding استفاده نمیکنم ، از همون شیِ اولیه و واحد برای ExtensionMethodViewModel استفاده میکنم اما درست کار میکنه . فرق شون چیه؟
چرا باید برای یکی ، مقدار جدیدی برای ExtensionMethodViewModel در نظر گرفت و برای یکی دیگه ، این کار لازم نیست؟

در نسخه اولیه شما یک مجموعه ComboBoxItem رو مشترکا برای همه ComboBox ها بکار می بردید، در نتیجه منبع اشتراکی داشتند و هر ComboBox ای رو که نشون می دادید همان آیتمی رو انتخاب کرده بود که در آخرین ComboBox انتخاب شده.

بله .
این ، برای وقتی بود که از یک شیِ واحد برای پروپرتیِ UI (که از نوع PoshtibangirToloUI بود) ، استفاده میکردم .
در این صورت ، از یک شیِ واحد برای پروپرتیِ FixedDriveComboBoxItems ئه PoshtibangirToloUI استفاده میشد . که منجر به این مشکل میشد . بخاطر اینکه هر دو کمبوباکس ، به یک شی از FixedDriveComboBoxItems و در نتیجه به یک شی از CollectionView متصل و Binding میشدند .
وقتی هم که شی جدیدی برای پروپرتیِ UIدر نظر میگرفتم ، مشکل اولش حل میشد . که دلیلش معلومه .

اما مشکل دومی زمانی حل میشد که شی جدیدی برای پروپرتیِ ExtensionMethodViewModel (که درون متد SetFixedDriveComboBoxItemsProperty ازش استفاده میشه در کد پست قبلی) در نظر بگیرم .
میخوام بدونم که این چه ربطی داره؟
یعنی وقتی که از شی واحد برای پروپرتیِ ExtensionMethodViewModel در PoshtibangirToloUI استفاده کنیم یا نکنیم ، چه تاثیری میذاره که منجر به حل شدن این مشکل دومی (که در پست قبلی با شکل کمبوباکس نشون و توضیح دادم) میشه؟

در ویرایش بعدی شما منبع ComboBox ها رو از هم تفکیک شون کردید ولی حالا همچنان یک مجموعه ComboBoxItem رو برای دفعات بعدی اجرای یک ComboBox حفظ می کنید و در نتیجه انتخاب قبلی ComboBox هم حفظ میشه.

وقتی که شیِ جدیدی در متد سازنده ی SettingWindow برای پروپرتیِ UI اش در نظر میگیرم ، چیزی که میگید ، درسته و اتفاق میافته . یعنی در این صورت ، مشکل اولی حل میشه اما مشکل دوم (که در پست قبلی عکسش را گذاشتم) ، پا برجاست .

مشکل دوم ، زمانی حل میشه که برای پروپرتیِ ExtensionMethodViewModel در PoshtibangirToloUI ، مقدار جدیدی در نظر گرفته بشه .
میخوام بدونم ارتباط مقدار جدید گرفتن برای پروپرتیِ ExtensionMethodViewModel در PoshtibangirToloUI ، با حل مشکل دومی ، چه ارتباطی داره؟

تشکر استاد .
 

the_king

مدیرکل انجمن
خیلی ممنون استاد .
نه .
وقتی که آیتم های کمبوباکس را Binding نکنم و از متد برای پر کردن آیتم های کمبوباکس استفاده کنم (در این صورت ، حتی در هر جا که پروپرتیِ مربوط به ViewModel و همچنین پروپرتیِ UI وجود داشته باشه ، اگه از شیِ واحدی برای این پروپرتی ها استفاده کنم) ، این مشکل وجود نخواهد داشت .
ازم من پرسیدید و من پاسخ دادم و گفتید نه. دیگه دلیلی نداره برای قانع کردن شما تلاش کنم. با نظر من مخالف هستید. قبول. اگر فکر میکنید پاسخ های من درست نیست دیگه از من سوال نکنید. چرا بحث با کسی که نظرش رو قبول ندارید رو ادامه می دهید؟
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ازم من پرسیدید و من پاسخ دادم و گفتید نه. دیگه دلیلی نداره برای قانع کردن شما تلاش کنم. با نظر من مخالف هستید. قبول. اگر فکر میکنید پاسخ های من درست نیست دیگه از من سوال نکنید. چرا بحث با کسی که نظرش رو قبول ندارید رو ادامه می دهید؟

خیلی ممنون استاد .
فکر میکنم متوجه ی دقیق سئوال نشدید .

چون من درباره ی تاثیرِ مقداردهیِ جدید برای پروپرتیِ ExtensionMethodViewModel در PoshtibangirToloUI در پست قبل پرسیدم :
"میخوام بدونم ارتباط مقدار جدید گرفتن برای پروپرتیِ ExtensionMethodViewModel در PoshtibangirToloUI ، با حل مشکل دومی ، چه ارتباطی داره؟"


در جواب تون که به ارتباطِ شیِ جدید دادن یا از یک شیِ واحد استفاده کردن برای این پروپرتی که نبود .
خیلی ممنون استاد .
 

the_king

مدیرکل انجمن
خیلی ممنون استاد .
فکر میکنم متوجه ی دقیق سئوال نشدید .

چون من درباره ی تاثیرِ مقداردهیِ جدید برای پروپرتیِ ExtensionMethodViewModel در PoshtibangirToloUI در پست قبل پرسیدم :
"میخوام بدونم ارتباط مقدار جدید گرفتن برای پروپرتیِ ExtensionMethodViewModel در PoshtibangirToloUI ، با حل مشکل دومی ، چه ارتباطی داره؟"
کدتون رو تفسیر کنید تا متوجه بشوید که هم چه ارتباطی بین اجزاء کدتون هست و هم چه ارتباطی با پاسخی که من داده بودم داره. من اگر ارتباط بین سوال شما و پاسخ خودم رو متوجه نشوم که من از سوال کردن بجا نیست.
در جواب تون که به ارتباطِ شیِ جدید دادن یا از یک شیِ واحد استفاده کردن برای این پروپرتی که نبود .
چون روال کدتون رو تفسیر نمی کنید، مسائلی که در بروز یک تفاوت نقشی ندارند رو موثر میدونید. رفتار یک کلاس ComboBox میتونه به رفتار کلاس و ساختار های دیگری که بهشون وابستگی نداره مربوط باشه؟ کد ComboBox رو که شما ننوشته اید، میتونه به کد کلاس X و Y ای که شما می نویسید وابسته باشه؟ همچین چیزی محال ئه. رفتار اون کلاس به روال داخل خود کلاس و مقدار فیلد ها و مشخصه های اون کلاس بستگی داره. روال داخل کلاسش که ثابت ئه و تغییر نکرده، چیزی که تغییر می کنه مقدار مشخصه های ComboBox ئه. بجای اینکه بررسی کنید که چه مقادیری به ComboBox داده اید که فلان رفتار رو داشته، تمرکز تون رو گذاشته اید روی پروپرتی ها و کلاس های پروژه تون.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
کدتون رو تفسیر کنید تا متوجه بشوید که هم چه ارتباطی بین اجزاء کدتون هست و هم چه ارتباطی با پاسخی که من داده بودم داره. من اگر ارتباط بین سوال شما و پاسخ خودم رو متوجه نشوم که من از سوال کردن بجا نیست.

چون روال کدتون رو تفسیر نمی کنید، مسائلی که در بروز یک تفاوت نقشی ندارند رو موثر میدونید. رفتار یک کلاس ComboBox میتونه به رفتار کلاس و ساختار های دیگری که بهشون وابستگی نداره مربوط باشه؟ کد ComboBox رو که شما ننوشته اید، میتونه به کد کلاس X و Y ای که شما می نویسید وابسته باشه؟ همچین چیزی محال ئه. رفتار اون کلاس به روال داخل خود کلاس و مقدار فیلد ها و مشخصه های اون کلاس بستگی داره. روال داخل کلاسش که ثابت ئه و تغییر نکرده، چیزی که تغییر می کنه مقدار مشخصه های ComboBox ئه. بجای اینکه بررسی کنید که چه مقادیری به ComboBox داده اید که فلان رفتار رو داشته، تمرکز تون رو گذاشته اید روی پروپرتی ها و کلاس های پروژه تون.

خیلی ممنون استاد .
توی ذهنم بارها تفسیر کردم . اما هر چی فکر میکنم ، رابطه ی شیِ جدید دادن به پروپرتیِ ExtensionMethodViewModel در PoshtibangirToloUI و حل شدن مشکل دوم را (زمان Binding کردن کمبوباکس) ، را نمیدونم از کجا نشات میگیره .

استاد ، همونطور که میدونید (یا حداقل برایِ منِ مبتدی) ، بررسی کردنِ ارتباط بین کدهامون مخصوصا زمانی که با رابط کاربری (کنترل های بصری) در ارتباط باشن ، کشفِ این ارتباط ، خیلی کار را پیچیده میکنه .
روالی در ویژال استودیو وجود داره که این کدها را تست کنیم و کشف کنیم؟

فرضا وقتی در کدهای xaml ، عمل Binding را برای ItemsSource ئه کمبوباکس تعیین میکنیم ، بخوایم هر وقت که اولین کدِ مربوط به این Binding ای که اجرا شد ، همونجا break point بشه و کد متوقف بشه تا بتونیم از اون به بعد ، آروم آروم کدها را trace و مسیریابی و بررسی کنیم . همچین چیزی ممکنه؟

چون breakpoint را تا جایی که میدونم ، فقط جایی یا در متد یا رویداد یا هر جایی که کدی اونجا نوشتیم ، میشه گذاشت . ولی فرضا ما نمیدونیم که اولین باری که کدهای مربوط به Binding ای که در xaml ایجاد کرده بودیم ، چه زمانی و در کدوم رویداد اتفاق میافته تا بشه از اون به بعد ، کدها را بررسی کنیم .

کلا همچین کاری شدنی هست؟
این unit testing که میگن ، به درد این جور جاها نمیخوره؟
کلا ویژال استودیو ، روالی برای این نوع از بررسی کدها ، در نظر نگرفت؟

تشکر استاد .
 

the_king

مدیرکل انجمن
خیلی ممنون استاد .
توی ذهنم بارها تفسیر کردم . اما هر چی فکر میکنم ، رابطه ی شیِ جدید دادن به پروپرتیِ ExtensionMethodViewModel در PoshtibangirToloUI و حل شدن مشکل دوم را (زمان Binding کردن کمبوباکس) ، را نمیدونم از کجا نشات میگیره .
چون جای اشتباه رو می گردید، یک روال A دارید و یک روال B که با n تا کلاس و m مشخصه کار مشابهی رو به روشهای متفاوتی با ComboBox ها انجام می دهند و رفتار ComboBox متفاوت شده. ممکنه این A و B کد های پیچیده و زیادی داشته باشند، آیا لازمه همه شون با هم مقایسه بشه؟ طبعا نه.
اهمیتی داره که روال A به چه روشی به ComboBox مقدار میده؟ نه. فقط مقداری که به مشخصه فلان میده مهم ئه.

روی چی باید متمرکز بشوید، چیزی که بررسی اش مساله رو حل کنه. الان چی مساله ما است؟ دلیل تفاوت در رفتار ComboBox، نه تفاوت در ساختار و کد های روال A و B. شما نمی خواهید A و B رو مقایسه کنید، نمی خواهید همه تفاوت های A و B رو لیست کنید، نمی خواهید کل A و B رو تفسیر کنید. فقط میخواهید بدانید چه تفاوتی در A و B هست که منجر به اون تفاوت در رفتار ComboBox شده. ممکنه ده ها تفاوت در A و B باشند که ربطی به مساله ما نداشته باشند، بی تاثیر باشند یا عامل فرعی باشند، بررسی تفاوت های A و B مساله رو حل نمی کنه.

حالا ComboBox ای که روال A استفاده می کنه با ComboBox ای که روالی B استفاده می کنه چه فرق ساختاری داره؟ هیچ فرقی. ComboBox که فرقی نداره، اما مقادیری که به ComboBox داده شده در دو روال فرق می کنه، تفاوت از همین مقادیر ناشی شده. پس کجا باید دنبال تفاوت بگردید؟ جایی که مقادیری به ComboBox داده اید. سوال ها چیه؟ اینکه چه زمان هایی مقدار می دهید، چه نوع داده ای می دهید، چه داده هایی می دهید و مقدار یک شیء تکراری است یا هر بار مقدار جدید ئه. فقط همین. به بقیه تفاوت ها کاری نداشته باشید.

دلیل تفاوت رو هم که قبلا من گفتم و حاضر ئه، فقط میخواهید خودتون بررسی کنید تا به اون نتیجه برسید یا اصلا نتیجه بگیرید که من اشتباه می کنم. یعنی الان هم یک نظریه برای تفاوت دارید و هم می دانید که کجا رو باید بگردید، فقط باید بررسی اش کنید تا ببینید درسته یا نه.
استاد ، همونطور که میدونید (یا حداقل برایِ منِ مبتدی) ، بررسی کردنِ ارتباط بین کدهامون مخصوصا زمانی که با رابط کاربری (کنترل های بصری) در ارتباط باشن ، کشفِ این ارتباط ، خیلی کار را پیچیده میکنه .
روالی در ویژال استودیو وجود داره که این کدها را تست کنیم و کشف کنیم؟
جایی که ComboBox هاتون قرار داره مشخص ئه، جایی که مقادیر به مشخصه هاش داده میشه هم مشخص ئه، مقادیری که ارسال میشه هم مشخص ئه، پس چیزی این وسط مبهم نیست که بخواهید کشف اش کنید. فقط باید بررسی کنید که چه مقادیری تحویل ComboBox می دهید. و چیزی که به ComboBox می دهید هم که اصلا پیچیده و عجیب غریب نیست، شما یکسری string رو بصورت ComboBoxItem درآورده اید و به ComboBox تحویل داده اید. به چه روشی اش هم مهم نیست، میخواد با Binding باشه یا نباشه. مقادیرشون "One" و "Two" و "Three" هم باشه فرقی نمی کنه، همون قضیه است. فقط گاهی شما ComboBoxItem قبلا استفاده شده رو به ComboBox می دهید و گاهی ComboBoxItem جدیدی که قبلا در ComboBox ای نبوده. گاهی برای هر پنجره مجموعه ComboBoxItem های اختصاصی دارید، گاهی اشتراکی. بقیه تفاوت ها در این مورد که میخواهید بررسی اش کنید نقش تعیین کننده نداره، تفاوت های فرعی رو بذارید کنار.
فرضا وقتی در کدهای xaml ، عمل Binding را برای ItemsSource ئه کمبوباکس تعیین میکنیم ، بخوایم هر وقت که اولین کدِ مربوط به این Binding ای که اجرا شد ، همونجا break point بشه و کد متوقف بشه تا بتونیم از اون به بعد ، آروم آروم کدها را trace و مسیریابی و بررسی کنیم . همچین چیزی ممکنه؟
نیازی نیست break ای باشه، در ضمن هم می توانید برای خود Binding ئه رخداد در نظر بگیرید و هم می توانید از طرف اون مبداء داده کدی اضافه کنید تا از دریافت مقدار مطلع بشوید. در نظر بگیرید که شما نمی خواهید رفتار ComboBox رو بررسی کنید، رفتار ComboBox مشخص ئه، شما فقط ببینید چه مقداری به اون فرضا ItemsSource می دهید، که طبعا این رو خودتون مطلع هستید که مقادیر شبیه به چیه و نیازی نیست برایش کدی رو debug کنید، و خودتون هم میتوانید راحت بفهمید که اشیاء هر بار از نو ایجاد می شوند یا همون اشیاء قبلی رو مجددا به ComboBox تحویل می دهید. این چیزها نیازی به debug کردن نداره.

و اون نکته کلیدی که قبل از حل مساله صورت مساله رو ساده کنید فراموش نکنید. شما می توانید یک پروژه ساده بسازید که دو پنجره داشته باشه، دو ComboBox و یک داده اولیه که فقط چند تا string ئه و ببینید 1- اشتراک یک مجموعه ComboBoxItem بین دو ComboBox و 2- نگهداری یک مجموعه ComboBoxItem مستقل از پنجره که موقع باز شدن مجدد پنجره همون رو به ComboBox تحویل میده و 3- ایجاد ComboBoxItem ها در هر بار باز شدن پنجره چه فرقی در رفتار ComboBox دارند. و بعد از نتیجه گیری اونها می توانید برگردید روی پروژه خودتون و ببینید چطور روی پروژه تون این حالت ها تکرار شده.
چون breakpoint را تا جایی که میدونم ، فقط جایی یا در متد یا رویداد یا هر جایی که کدی اونجا نوشتیم ، میشه گذاشت . ولی فرضا ما نمیدونیم که اولین باری که کدهای مربوط به Binding ای که در xaml ایجاد کرده بودیم ، چه زمانی و در کدوم رویداد اتفاق میافته تا بشه از اون به بعد ، کدها را بررسی کنیم .
برای همچین موضوعی کاربردی نداره، دقت کنید که شما نمی خواهید الان الگوریتم کدی رو بررسی کنید، فقط پاسخ اون چند سوال رو میخواهید. برای پاسخ دادن به اون سوال ها لازم نیست خیلی در گیر روالهای پروژه تون باشید یا به زمان بندی ها توجه کنید.
کلا همچین کاری شدنی هست؟
خیلی کار ها شدنی است اما برای این موضوعی که الان دارید حل اش می کنید نیازی به اینکار ها نیست.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
خیلی ممنون استاد .
سعی میکنم به دقت ، مواردی که گفتین را بررسی کنم (که تاکید بیشترتون روی بررسی مقدار ComboBoxItem بود) . هر چند بررسی کرده بودم.

اما قبل از اون ، چند مدتی هست که وقتی برنامه را اجرا میکنم ، ارورِ Binding ئه زیر را برای ComboBoxItem زمان اجرای برنامه میده (باعث متوقف شدن برنامه نمیشه . چون ارور بایندینگ هست) .
در وهله ی اول ، به نظرم میرسه که ربطی به مقدارِ ComboBoxItem برای این جریان نباشه (چون بایندینگ شون را قطع کردم و جایگزینش ، آرایه ای از string ها را به عنوان items در کد xaml دادم ، باز همین همین ارور را میداد) :

1.JPG


به نظرم میاد که مربوط به تمپلیت ای که براش نوشتم باشه .
کد استایل ئه مربوط به ComboBoxItem ام اینه :

XML:
    <Style TargetType="{x:Type ComboBoxItem}">
        <Setter Property="SnapsToDevicePixels" Value="True"/>
        <Setter Property="Template" Value="{StaticResource ComboBoxItemTemplate}"/>
    </Style>

کد مربوط به تمپلیت ComboBoxItem ام اینه :


XML:
    <ControlTemplate x:Key="ComboBoxItemTemplate" TargetType="{x:Type ComboBoxItem}">
        <Border x:Name="combItemBorder" Background="Transparent" BorderThickness="1" BorderBrush="Transparent" SnapsToDevicePixels="True">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="20"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>

                <Path x:Name="tickPath" Grid.Column="0" Visibility="Hidden"  Stroke="{DynamicResource combItem_MouseEnterColor}" StrokeThickness="1" Fill="{DynamicResource combItem_MouseEnterColor}" StrokeStartLineCap="Triangle" StrokeEndLineCap="Triangle" Data="{Binding Data, Source={StaticResource checkboxTickPath}}"/>
                <ContentPresenter x:Name="combItemPresenter" Grid.Column="1" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
            </Grid>
        </Border>

        <ControlTemplate.Triggers>
            <Trigger Property="IsSelected" Value="True">
                <Setter TargetName="tickPath" Property="Visibility" Value="Visible"/>
                <Setter TargetName="combItemPresenter" Property="TextBlock.Foreground" Value="{DynamicResource combItem_MouseEnterColor}"/>
            </Trigger>
            <Trigger Property="IsHighlighted" Value="True">
                <Setter TargetName="combItemBorder" Property="BorderBrush" Value="{DynamicResource combItem_MouseEnterColor}"/>
            </Trigger>
            <Trigger Property="FlowDirection" Value="RightToLeft">
                <Setter TargetName="tickPath" Property="FlowDirection" Value="LeftToRight"/>
                <Setter TargetName="tickPath" Property="Margin" Value="0,0,5,0"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>


اما باز هم انگار که این ارور ، برای این تمپلیت نیست . چون :
1 - اینکه مشکوک ترین قسمت از کد تمپلیت که مربوط به این ارور ممکنه باشه ، کدِ زیر هست :

XML:
                <ContentPresenter x:Name="combItemPresenter" Grid.Column="1" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>

و برای پروپرتیِ HorizontalAlignment که TemplateBinding انجام دادم .
اما اولا که وقتی این تیکه از کد را هم حذف کردم ، باز هم همین ارور وجود داشت .
دوما اینکه در این ارور ، Binding Target Property (یا همون Target) را ، پروپرتیِ ComboBoxItem.HorizontalContentAlignment اعلام میکنه اما Target ئه من ، در TemplateBinding ئه بالا ، پروپرتیِ ComboBoxItem.HorizontalAlignment هست .

2 - جالب اینکه من در کد استایل اش (در بالا) ، به Style اش هم یه کلید اختصاصی دادم و در هیچ یک از کمبوباکسم از این کلید ، استفاده نکردم . یعنی هیچ یک از کمبوباکس در پروژه ام ، از استایل یا تمپلیتِ ComboBoxItem ای که نوشتم ، استفاده نمیکردن ، اما باز هم همین ارور را میداد .

3 - جالب تر اینکه همین استایل و تمپلیت را هم در پروژه ی تمرینی دیگه دارم استفاده میکنم و اونجا ، اروری نمیده .

4 - جالب تر از همه اینکه در همین پروژه ، تا چند وقت پیش ، همین استایل و تمپلیت بودن اما این ارور وجود نداشت .
نمیدونم ، شاید به قضیه ی بایندینگ کردن به پروپرتیِ FixedDriveComboBoxItems ئه PoshtibangirToloUI که قبلا گفته بودم ، ربط داشته باشه که اون هم فکر نکنم . چون Binding های کمبوباکس به این پروپرتی را هم حذف کرده بودم و باز این ارور وجود داشت .

هر چند شاید به بایندینگ کردن به پروپرتیِ FixedDriveComboBoxItems ربط نداشته باشه اما شاید به کدها و روال هایی که برای این پروپرتی یا ViewModel ها اضافه کردم ، ربط داشته باشه (که اون هم بهش مشکوکم و شاید برای اینها هم نباشه) . آخه چون تقریبا این اواخر که روال و کدهای مربوط به این پروپرتی را داشتم اضافه میکردم ، انگار (دقیقا نمیدونم) از اون به بعد ، این ارور ایجاد شد . قبلش این ارور را نمیداد .

میدونین کجا باید دنبال این ارور بگردم؟
تشکر استاد .
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ComboBoxItem هایی دارید که خودشون هستند ولی ItemsControl ای که باید والدشون باشه دیگه در دسترس نیست.

آها . خیلی ممنون استاد .
فکر کنم به متد FillFixedDriveComboBoxItemsProperty یا به خودِ FixedDriveComboBoxItems برگرده که شی ای از List<ComboBoxItems> برمیگردونه اما ComboBoxItems هاشون ، کنترلِ ComboBox را ندارن .
حالا بیشتر بررسی میکنم .

خیلی ممنون استاد .
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
یک مجموعه از ComboBoxItem ها تشکیل شده که علاوه بر نگهداری رشته خروجی DriveInfoFormatted هر رفتاری که در ComboBox در مورد اون آیتم انجام میشه، فرضا انتخاب شدن آیتم رو (IsSelected) حفظ می کنه. ComboBox تغییرات رو روی این ComboBoxItem اعمال کرده و شما هم حفظ اش کردید. اگر همچین مجموعه ای حفظ بشه، در دفعات بعدی ComboBox نتیجه فعالیت قبلی رو بخاطر داره و همون رو نشون میده.

ComboBoxItem هایی دارید که خودشون هستند ولی ItemsControl ای که باید والدشون باشه دیگه در دسترس نیست.

خیلی ممنون استاد .
واقعا کمکم کردین و خدا بوسیله ی شما ، مشکلم را حل کرد . :rose: مدتی بود واسه ی این مشکل گیر کرده بودم .

مشکل را تقریبا احتمالا یافتم .
چند مدتی بود اون ارور را میداد و فکر هم نمیکردم که این ارور ، به مشکل قبلی مربوط باشه . امروز گفتم اول برم این ارورِ بایندینگ را حل کنم و بعدا مجددا سراغ حل مشکل قبلی برم (که خدا این رو جلو راهم گذاشت) .

بله استاد ، هر دوی این مشکلات (هم ارور بایندینگ و هم مشکل رفتار کمبوباکس) ، به نوعِ Source شون که پروپرتیِ FixedDriveComboBoxItems و از نوعِ List<ComboBoxItem> بود ، بود .

من نوعِ این پروپرتی را به List<string> تغییر دادم و همه ی مشکلات با هم حل شدن (شی ها برای پروپرتی های UI و همچنین برای پروپرتی های مربوط به ViewModel در تمام کلاس ها ، یک شیِ واحد هستند و شی جدیدی در کلاس های مختلف ، نیستن) :

- یعنی دیگه هم ارور بایندینگ را نمیده .

- هم مشکلِ اینکه وقتی در کمبوباکسِ صفحه ی SettingWindow ، یه آیتمی را انتخاب میکردم و بعد در کمبوباکسِ صفحه ی ExceptionManagementWindow ، همون آیتم ، انتخاب شده بود و برعکسش ، درست شد (با اونکه پروپرتیِ UI ، در همه ی کلاس ها از یک شیِ واحد استفاده میکنن و در نتیجه ، هر دو کمبوباکس ، به شیِ واحد از CollectionView متصل شده ، اما چون در این کمبوباکس ها ، مقدارِ پروپرتیِ IsSynchronizedWithCurrentItem ست نشده ، این مشکل هم حل شد) .
البته الان که میبینم ، این مشکل ، دقیقا شبیه اون نیست . چون وقتی پروپرتیِ IsSynchronizedWithCurrentItem را true میکنیم ، مقدارِ انتخاب شده در تمپلیتی که از کمبوباکس استفاده میکنم ، علاوه بر اینکه در قسمتِ آیتم ها هم تیک میخوره ، در قسمتِ TextBox ئه کمبوباکس هم آیتم انتخابی ، نوشته میشه . اما در مشکل قبلی ، فقط تیک میخورد) .

- و هم اینکه رفتار یک کمبوباکس وقتی چندین بار وارد صفحه اش میشدیم ، با چندین انتخاب در آیتم ها ، چندین تای اونها را انتخاب میکرد (که عکسش را در صفحه ی قبل نشون دادم) ، هم حل شد .

-----------------------------

الان استاد ، این مشکلات ، ربط به این داره که چون داریم از کمبوباکس استفاده میکنیم ، پس نباید پروپرتیِ Source مون از نوعِ آیتم های کمبوباکس ، یعنی از نوعِ ComboBoxItem باشه؟
اگه آره ، من متوجه ی ربط شون نشدم . چرا باید با انتخاب نوع ComboBoxItem ، این مشکلات پیش بیاد؟
اگه نه ، پس بخاطر چیه که با تغییر نوع داده ی این پروپرتی ، همه ی مشکلات حل شد؟

هر چند ، متوجه نشدم چرا وقتی نوع این پروپرتی ، ComboBoxItem بود ، با شیِ جدید دادن به پروپرتی های مربوط به ViewModel و UI ، این مشکل حل میشد .


======================

اما سئوال مهم اینه که اولا ، کلا آیا نمیشه از نوعِ ComboBoxItem استفاده کنم (جوری که مثل List<String> ، که مشکلی پیش نمیاد ، این مشکلات پیش نیاد) ؟ و اساسا چرا وقتی از ComboBoxItem استفاده میکنم ، این مشکلات پیش میاد؟

چرا وقتی که بایندینگ نمیکردم و صرفا با متد ، در رویداد لود ، کمبوباکس را با همین نوعِ ComboBoxItem پر میکردم ، این مشکلات بوجود نمیومد (بجز ارور بایندینگ که مشخص بود و دلیلش را گفتین) ؟


مهمتر اینکه ، من اساسا نوعِ ComboBoxItem را انتخاب کردم چون بتونم با مقدارِ پروپرتیِ Content اش ، مقدارِ رشته ای را در آیتم ها نمایش بدم و علاوه بر اون ، در پروپرتیِ Tag اش ، مقدار شیِ DriveInfo را بریزم تا بتونم وقتی که کاربر ، آیتمی را انتخاب کرد ، به شیِ DriveInfo ئه مربوط به اون آیتم ، (به راحتی در همون کمبوباکس) دسترسی داشته باشم .

یعنی یک نوعی را میخوام به عنوان ItemsSource ئه کمبوباکس انتخاب کنم که 2 نوع را در خودش ذخیره کنه .
حالا که دقیق نمیدونم چرا نوع ComboBoxItem نمیشه ، شما ، جایگزین این را چی پیشنهاد میدین که 2 مقدار بشه در اون ذخیره کرد ولی یک مقدار را فقط در معرض نمایش بذاره؟

فرضا شاید بشه نوعِ لیستی از دیکشنری را گفت . فرضا List<Dictionary<string, DriveInfo>> . اما در این صورت ، در Binding ئه xaml ، چی بنویسم که بفهمه من فقط اون قسمت و نوعِ string اش را میخوام در آیتم های کمبوباکس به نمایش بذارم و نشون بدم؟
یا هر نوع دیگه ای که پیشنهاد میدین که نمیدونم؟

خیلی ممنون استاد . :rose:
 

the_king

مدیرکل انجمن
الان استاد ، این مشکلات ، ربط به این داره که چون داریم از کمبوباکس استفاده میکنیم ، پس نباید پروپرتیِ Source مون از نوعِ آیتم های کمبوباکس ، یعنی از نوعِ ComboBoxItem باشه؟
مشکل از خود نوع اش نیست، از اینه که ComboBoxItem چیزی نیست که بخواهید دست دومش رو برای ComboBox دیگری نگه دارید.
ComboBoxItem برای استفاده در یک ComboBox مناسبه و وقتی ComboBox از بین رفت اصولا باید اون ComboBoxItem هم که قبلا استفاده شده دور انداخته بشه. شما اگر هر بار برای ComboBox جدید اشیاء ComboBoxItem جدیدی میساختید مشکلی با نوع داده اش نداشتید.
اگه آره ، من متوجه ی ربط شون نشدم . چرا باید با انتخاب نوع ComboBoxItem ، این مشکلات پیش بیاد؟
گفتم بهتون، چون ComboBoxItem تمامی آنچه ComboBox روی آیتم انجام میده رو داخلش حفظ می کنه، فقط داده شما نیست. مشخصه های ComboBoxItem رو ببینید، این اطلاعاتی که نگه میداره چیزی نیست که شما بخواهید بعد از اینکه کار تون با ComboBox تموم شد برای ComboBox بعدی نگهدارید. مثل اینه که من پنجره رو نابود کنم، اما بخواهم TextBox های داخلش رو برای پنجره بعدی نگهدارم. اون TextBox دیگه برای پنجره دیگری نباید استفاده بشه، باید دور انداخته بشه و پنجره جدید برای خودش TextBox جدید بسازه.
هر چند ، متوجه نشدم چرا وقتی نوع این پروپرتی ، ComboBoxItem بود ، با شیِ جدید دادن به پروپرتی های مربوط به ViewModel و UI ، این مشکل حل میشد
چون برای هر ComboBox اشیاء ComboBoxItem جدید میساختید، دست دوم قبلی بهش تحویل نمی دادید. همون تفاوتی که گفته بودم.
.
اما سئوال مهم اینه که اولا ، کلا آیا نمیشه از نوعِ ComboBoxItem استفاده کنم (جوری که مثل List<String> ، که مشکلی پیش نمیاد ، این مشکلات پیش نیاد) ؟ و اساسا چرا وقتی از ComboBoxItem استفاده میکنم ، این مشکلات پیش میاد؟
توضیح دادم.
چرا وقتی که بایندینگ نمیکردم و صرفا با متد ، در رویداد لود ، کمبوباکس را با همین نوعِ ComboBoxItem پر میکردم ، این مشکلات بوجود نمیومد (بجز ارور بایندینگ که مشخص بود و دلیلش را گفتین) ؟
چون منبع داده تون دیگه یکسری ComboBoxItem از قبل آماده نبود که داخل مشخصه ای انبار کرده باشید، هر بار ComboBoxItem های جدیدی می ساختید و در ComboBox پر می کردید.
مهمتر اینکه ، من اساسا نوعِ ComboBoxItem را انتخاب کردم چون بتونم با مقدارِ پروپرتیِ Content اش ، مقدارِ رشته ای را در آیتم ها نمایش بدم و علاوه بر اون ، در پروپرتیِ Tag اش ، مقدار شیِ DriveInfo را بریزم تا بتونم وقتی که کاربر ، آیتمی را انتخاب کرد ، به شیِ DriveInfo ئه مربوط به اون آیتم ، (به راحتی در همون کمبوباکس) دسترسی داشته باشم .
برای اینکه راه حل زیاد ئه، مثلا می توانید یک کلاس بسازید و ToString اش رو override کنید تا اون متن مربوط به مشخصه خاص رو برگردونید تا در نمایش داخل ComboBox بصورت خودکار استفاده بشه و در اون کلاس یک مشخصه هم برای DriveInfo اختصاص بدهید.
یعنی یک نوعی را میخوام به عنوان ItemsSource ئه کمبوباکس انتخاب کنم که 2 نوع را در خودش ذخیره کنه .
حالا که دقیق نمیدونم چرا نوع ComboBoxItem نمیشه ، شما ، جایگزین این را چی پیشنهاد میدین که 2 مقدار بشه در اون ذخیره کرد ولی یک مقدار را فقط در معرض نمایش بذاره؟
ایراد در نحوه استفاده از ComboBoxItem بود، نه خودش. ولی اگر میخواهید بعد از بسته شدن پنجره و نابود شدن ComboBox همچنان از اون ComboBoxItem استفاده کنید، نوع داده مناسبی نیست، بهتره از ComboBoxItem برای نگهداری داده استفاده نکنید.
فرضا شاید بشه نوعِ لیستی از دیکشنری را گفت . فرضا List<Dictionary<string, DriveInfo>> . اما در این صورت ، در Binding ئه xaml ، چی بنویسم که بفهمه من فقط اون قسمت و نوعِ string اش را میخوام در آیتم های کمبوباکس به نمایش بذارم و نشون بدم؟
یا هر نوع دیگه ای که پیشنهاد میدین که نمیدونم؟
اگر نمیخواستید داخل ComboBox متن رو نمایش بدهید، KeyValuePair مناسب بود، اما چون نیاز به فرمت اختصاصی داره تا Key یا Value بصورت متن دربیاد، بهتره یک کلاس اختصاصی بسازید که با ToString تصمیم بگیرید چه متنی ازش خروجی گرفته بشه و هر تعداد مشخصه که خواستید بهش اضافه کنید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
مشکل از خود نوع اش نیست، از اینه که ComboBoxItem چیزی نیست که بخواهید دست دومش رو برای ComboBox دیگری نگه دارید.
ComboBoxItem برای استفاده در یک ComboBox مناسبه و وقتی ComboBox از بین رفت اصولا باید اون ComboBoxItem هم که قبلا استفاده شده دور انداخته بشه. شما اگر هر بار برای ComboBox جدید اشیاء ComboBoxItem جدیدی میساختید مشکلی با نوع داده اش نداشتید.

گفتم بهتون، چون ComboBoxItem تمامی آنچه ComboBox روی آیتم انجام میده رو داخلش حفظ می کنه، فقط داده شما نیست. مشخصه های ComboBoxItem رو ببینید، این اطلاعاتی که نگه میداره چیزی نیست که شما بخواهید بعد از اینکه کار تون با ComboBox تموم شد برای ComboBox بعدی نگهدارید.
مثل اینه که من پنجره رو نابود کنم، اما بخواهم TextBox های داخلش رو برای پنجره بعدی نگهدارم. اون TextBox دیگه برای پنجره دیگری نباید استفاده بشه، باید دور انداخته بشه و پنجره جدید برای خودش TextBox جدید بسازه.

سلامی مجدد
خیلی ممنون استاد .

پس دلیل اینکه چرا نباید (در این کاری که میخوام انجام بدم) ، برای آیتم های کمبوباکس ، از ComboBoxItem استفاده کنم ، همین چیزهایی هست که گفتید و بولد کردم . درسته؟
همچنین برای هر نوع دیگه ای که از نوع Item باشه ، مثل ListBoxItem و ... هم همینطوره. درسته؟

یعنی نوعِ ComboBoxItem ، چون اطلاعات مربوط به آیتم ها را در خودش نگه میداره (مثل آیتم انتخاب شده و خیلی موارد دیگه) و هر دفعه هم ازش استفاده میکنه ، پس به درد این نمیخوره که شیِ ComboBoxItem ، حتی در دفعه ی بعد هم به همون شیِ ComboBox که قبلا بهش نسبت داده شده بود ، مجددا تعلق بگیره .
در کل ، باید هر بار ، شیِ جدیدی از ComboBoxItem ، حتی به همون کمبوباکس که در رابط کاربری بود ، تعلق بگیره .

نهایتا برای رد کردن این مشکل ، بهتره که بجای استفاده از نوعِ کالکشنی از ComboBoxItem یا ListBoxItem و ... ، از نوع دیگه ای استفاده کنم .


چون برای هر ComboBox اشیاء ComboBoxItem جدید میساختید، دست دوم قبلی بهش تحویل نمی دادید. همون تفاوتی که گفته بودم.
.


ببخشید ، منظورم شیِ جدید دادن به پروپرتیِ ViewModel بود .
یعنی متوجه نشدم چرا وقتی نوع این پروپرتی ، ComboBoxItem بود ، با شیِ جدید دادن به پروپرتیِ ExtensionMethodViewModel ، این مشکل حل میشد .

چون شیِ جدیدِ ComboBoxItem (که نوع پروپرتیِ FixedDriveComboBoxItems بود) ، زمانی ساخته میشد که مقدار جدیدی برای پروپرتیِ UI در نظر میگرفتم . بنابراین نباید ربطی به شیِ جدید دادن به پروپرتیِ ExtensionMethodViewModel میداشت .

برای اینکه راه حل زیاد ئه، مثلا می توانید یک کلاس بسازید و ToString اش رو override کنید تا اون متن مربوط به مشخصه خاص رو برگردونید تا در نمایش داخل ComboBox بصورت خودکار استفاده بشه و در اون کلاس یک مشخصه هم برای DriveInfo اختصاص بدهید.

ایراد در نحوه استفاده از ComboBoxItem بود، نه خودش. ولی اگر میخواهید بعد از بسته شدن پنجره و نابود شدن ComboBox همچنان از اون ComboBoxItem استفاده کنید، نوع داده مناسبی نیست، بهتره از ComboBoxItem برای نگهداری داده استفاده نکنید.

اگر نمیخواستید داخل ComboBox متن رو نمایش بدهید، KeyValuePair مناسب بود، اما چون نیاز به فرمت اختصاصی داره تا Key یا Value بصورت متن دربیاد، بهتره یک کلاس اختصاصی بسازید که با ToString تصمیم بگیرید چه متنی ازش خروجی گرفته بشه و هر تعداد مشخصه که خواستید بهش اضافه کنید.

بله . خیلی ممنون .
البته قبل از اینکه نوع پروپرتیِ FixedDriveComboBoxItems را از نوع کالکشنی از ComboBoxItem ها در نظر بگیرم ، جایگزینا به ایجاد کلاس سفارشی هم فکر کرده بودم . ولی چون نوعِ ComboBoxItem ، شامل دو پروپرتی بود که نیازم را برطرف میکرد ، این نوع را انتخاب کرده بودم اما فکر نمیکردم که هر شیِ ComboBoxItem را باید به هر ComboBox بدیم و هم اینکه اطلاعاتِ کمبوباکس را هم در خودش ذخیره میکنه و باعث اون مشکلات میشه .

------

اسم این کلاس را ItemsControlCustomItem میذارم . میخوام برای موارد دیگه مثل آیتم های لیست باکس و ... هم ازش استفاده کنم . (یکی از مکافات من ، انتخاب نام مناسب برای پروپرتی و کلاس ها و ... هست) . نامش خوبه؟
هر چند ، نامش گیج و گمراه کننده میشه اما احتمالا با مثما هست .

اما این کلاس ، جزء View محسوب میشه دیگه . درسته؟
چون میخوام شیِ این کلاس را به ComboBox و ListBox و اینها (و کلا به المنت های View ام) ، بصورت مستقیم بدم .

--------------------------

یه چیزی خارج از این بحث اینکه من خیلی از اسنادِ مربوط به مطالب wpf در سایت مایکروسافت را میبینم که تاریخ ایجاد سند را مخصوصا از سال 2017 به بعد زدن (بسیاری شونم هم مربوط به امسال هستن) . حتی اسناد مربوط به .Net Framework را .
فرضا مقاله ی آموزشیِ "Data binding overview in WPF" برای ماه 12 ام سال 2020 اون هم برای .Net Framework زدن .
اینها یعنی چی؟
یعنی مایکروسافت قبل از اینها ، اسناد مربوط به wpf برای آموزش را نداشت؟
wpf که سال 2006 ساخته شده بود .
اگه اینطوره ، ما هیچ ، پس خودِ خارجی ها ، با تکیه بر چه اسنادی wpf را تا قبل از اینکه این اسناد ارائه بشن (که اغلب مربوط به سال 2017 به بعد هست) ، یاد میگرفتن؟
یا اینکه به معنی این هست که قبل از اینها هم این مقالات یا شبیه این مقالات ، بوده اما زمان آخرین ویرایش شون ، اون موقع بوده؟

تشکر استاد .
 
آخرین ویرایش:

the_king

مدیرکل انجمن
سلامی مجدد
خیلی ممنون استاد .

پس دلیل اینکه چرا نباید (در این کاری که میخوام انجام بدم) ، برای آیتم های کمبوباکس ، از ComboBoxItem استفاده کنم ، همین چیزهایی هست که گفتید و بولد کردم . درسته؟
بله.
همچنین برای هر نوع دیگه ای که از نوع Item باشه ، مثل ListBoxItem و ... هم همینطوره. درسته؟
همچین قاعده کلی ای نداریم.
ببخشید ، منظورم شیِ جدید دادن به پروپرتیِ ViewModel بود .
یعنی متوجه نشدم چرا وقتی نوع این پروپرتی ، ComboBoxItem بود ، با شیِ جدید دادن به پروپرتیِ ExtensionMethodViewModel ، این مشکل حل میشد .
به نظرتون چطور باید متوجه شد؟ مشکل خود به خود که حل نشده، مشکل وقتی حل شده که مقادیری که به ComboBox می دهید تغییری کرده باشه.
اگر اون بررسی که قبلا گفتم بکنید، می فهمید که در روال فلان دارید به ComboBox مقادیر جدید می دهید یا مقادیر تکراری که به ComboBox قبلی داده بودید.
چون شیِ جدیدِ ComboBoxItem (که نوع پروپرتیِ FixedDriveComboBoxItems بود) ، زمانی ساخته میشد که مقدار جدیدی برای پروپرتیِ UI در نظر میگرفتم . بنابراین نباید ربطی به شیِ جدید دادن به پروپرتیِ ExtensionMethodViewModel میداشت .
الان یک استدلال تو ذهن تون هست که اجرای کد نشون میده اشتباه ئه، و میخواهید ببینید کجا اشتباه می کنید.
بررسی کردن اینکه در ComboBox مقادیر جدید و قدیم فرق کرده اند یا همون قبلی ها هستند که کار سختی نیست، می توانید با متغیر های static و دو سه تا دکمه مقدار به متغیر انتقال بدهید و در دفعه بعد بررسی کنید که مقادیر فرق می کنند یا همان قبلی ها هستند.
اسم این کلاس را ItemsControlCustomItem میذارم . میخوام برای موارد دیگه مثل آیتم های لیست باکس و ... هم ازش استفاده کنم . (یکی از مکافات من ، انتخاب نام مناسب برای پروپرتی و کلاس ها و ... هست) . نامش خوبه؟
هر چند ، نامش گیج و گمراه کننده میشه اما احتمالا با مثما هست .
نظری ندارم.
اما این کلاس ، جزء View محسوب میشه دیگه . درسته؟
اگر از Model میاد و میخواهید در View استفاده اش کنید، جزئی از ViewModel محسوب میشه.
اما اگر ربطی به Model نداره، بله، جزئی از View محسوب میشه.
چون میخوام شیِ این کلاس را به ComboBox و ListBox و اینها (و کلا به المنت های View ام) ، بصورت مستقیم بدم .
چه در ViewModel و چه در View تعریفش کنید این امکان رو دارید.
یه چیزی خارج از این بحث اینکه من خیلی از اسنادِ مربوط به مطالب wpf در سایت مایکروسافت را میبینم که تاریخ ایجاد سند را مخصوصا از سال 2017 به بعد زدن (بسیاری شونم هم مربوط به امسال هستن) . حتی اسناد مربوط به .Net Framework را .
فرضا مقاله ی آموزشیِ "Data binding overview in WPF" برای ماه 12 ام سال 2020 اون هم برای .Net Framework زدن .
اینها یعنی چی؟
یعنی اولا منابع دائم بازبینی و ویرایش می شوند، فرضا اگر در ویندوز جدید نکته ای لازم باشه مطلب ویرایش میشه، ثانیا منابع مکررا با تغییر سیستم بازنویسی می شوند، از نو نوشته می شوند، مثلا وقتی Microsoft Docs جایگزین MSDN شد، مقالاتی که در MSDN بودند باید از نو بازنویسی می شدند، طبعا در بازنویسی تاریخ نگارش شون فرق می کنه.
یعنی مایکروسافت قبل از اینها ، اسناد مربوط به wpf برای آموزش را نداشت؟
نه، همچین تعبیری درست نیست. فرضا راهنمای GetWindowLongA در قالب جدید نگارش 2018 ئه، طبعا قالب و متنش با چیزی که در MSDN سال 2001 بود کلی فرق داره. اما GetWindowLongA سال 1993 هم راهنما داشت، موضوع جدیدی نیست که قبل از 2018 نبوده باشه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلامی مجدد
خیلی ممنون استاد .

این رو برای خودم میگم برای بعدا اگه مرور میکنم و اینها (نمیدونم قبلا این نکته را مرور کردیم یا نه) :
اینکه ObservableCollection ، برای زمانی که اعضای کالشن تغییر کنن ، به شیِ Binding ای که بهش متصل شده میتونه خبر بده اما برای زمانی که کلِ کالکشن (و مجموعه) تغییر کنه ، نمیتونه این کار را کنه .

برای زمانی که کل کالکشن ، به شیِ جدیدی تغییر کنه (نه اعضای کالکشن) ، میتونیم با پیاده سازیِ اینترفیس INotifyPropertyChanged ، به شیِ Binding ای که به پروپرتیِ ObservableCollection مون متصل شد ، اطلاع بدیم .
مثل تمام اعضای معمولی که وقتی شیِ شون تغییر میکرد (نه عضوِ خاص از اون شی) که با پیاده سازیِ اینترفیس INotifyPropertyChanged در اون پروپرتی ، میتونستیم به شیِ Binding ای که بهش متصل شد ، اطلاع بدیم .


========================


اگر اون بررسی که قبلا گفتم بکنید، می فهمید که در روال فلان دارید به ComboBox مقادیر جدید می دهید یا مقادیر تکراری که به ComboBox قبلی داده بودید.

الان یک استدلال تو ذهن تون هست که اجرای کد نشون میده اشتباه ئه، و میخواهید ببینید کجا اشتباه می کنید.
بررسی کردن اینکه در ComboBox مقادیر جدید و قدیم فرق کرده اند یا همون قبلی ها هستند که کار سختی نیست، می توانید با متغیر های static و دو سه تا دکمه مقدار به متغیر انتقال بدهید و در دفعه بعد بررسی کنید که مقادیر فرق می کنند یا همان قبلی ها هستند.

خیلی ممنون استاد .
این طور تست کردم که در پنجره ی SettingWindow و در رویداد SelectDriveComboBox_TargetUpdated ئه مربوط به کمبوباکس ، کد زیر را نوشتم :

C#:
        private System.Collections.ObjectModel.ObservableCollection<ComboBoxItem> myComboBoxItems;
        private void SelectDriveComboBox_TargetUpdated(object sender, DataTransferEventArgs e)
        {
            if (myComboBoxItems != null)
            {
                bool res = object.ReferenceEquals(myComboBoxItems, (sender as ComboBox).ItemsSource as System.Collections.ObjectModel.ObservableCollection<ComboBoxItem>);
                MessageBox.Show(res.ToString());
            }

            myComboBoxItems = (sender as ComboBox).ItemsSource as System.Collections.ObjectModel.ObservableCollection<ComboBoxItem>;
        }

پروپرتیِ NotifyOnTargetUpdated در شیِ Binding ئه کمبوباکس را هم true کردم .
به پروپرتی های UI و ViewModel ها ، مقداری ندادم و همه شون شی واحدی بودن .
بنابراین پیام MessageBox.Show در کد بالا داده نشد .
پروپرتیِ UI را فقط شی جدیدی در لود ویندوز دادم که باز هم پیام داده نشد .
پروپرتی های UI و ViewModel ها را شی جدیدی در متد سازنده دادم اما این بار ، برخلاف دفعات قبل ، در کمبوباکس، اصلا آیتمی لیست نشد و خالی موند . نمیدونم چرا . دفعه ی قبل این طور نبود . به رویداد NotifyOnTargetUpdated ربطی نداره . این رویداد را هم غیر فعال کرده بودم ، باز هم همین طور بود .

حالا شاید زیاد مهم نباشه . چون میخوام کلا نوع اون پروپرتی را عوض کنم دیگه . (شاید هم مهم باشه و من ندونم و دفعات بعدی بخاطر ندونستن اش گیر کنم) .
به هر حال ، خیلی ممنون استاد .
 

the_king

مدیرکل انجمن
سلامی مجدد
خیلی ممنون استاد .

این رو برای خودم میگم برای بعدا اگه مرور میکنم و اینها (نمیدونم قبلا این نکته را مرور کردیم یا نه) :
اینکه ObservableCollection ، برای زمانی که اعضای کالشن تغییر کنن ، به شیِ Binding ای که بهش متصل شده میتونه خبر بده اما برای زمانی که کلِ کالکشن (و مجموعه) تغییر کنه ، نمیتونه این کار را کنه .
تفسیر درستی نیست، نمی تونه اینکار رو بکنه معنی نمیده، تغییری نمی کنه که بخواد اطلاع بده. شما از دید خود اون شیء تغییری نمی بینید که بخواد اطلاع بده. مجموعه ObservableCollection یا A یا هر نوع دیگری نمیتونه به مجموعه دیگری تغییر کرده باشه. شما با چه کدی می توانید شیء a رو به شئ دیگری تبدیل کنید؟ در #C همچین رخدادی نداریم. اصلا موضوع نوع داده خاصی مثل ObservableCollection نیست، خیلی کلی ئه، تصور کنید نوع اش ObservableCollection نیست و هر نوع دیگری باشه. وقتی شیء تغییر نمی کنه چه اطلاعی بده؟

فرضا یک نوع Collection با نام کلاس A دارید و ازش یک شیء در متغیر a1 دارید و اون شیء رو داخل مشخصه X قرار می دهید، یعنی ;X = a1
مهم نیست a1 چند تا عضو داره، مهم اینه که یک شیء ئه.
حالا یک شیء دیگر از همون نوع مجموعه A میسازید که در متغیر a2 قرار داره و در X قرار می دهید، یعنی ;X = a2
حالا مقدار X بازنویسی شده، مقدار مشخصه X تغییر کرده، به یک مجموعه دیگه اشاره می کنه، اما آیا این تغییر تاثیری روی a1 داره؟ نه. حالا چه بلایی سر اون شیء که در a1 هست اومده؟ هیچی. شیء اش تغییر کرده؟ خیر. اون شیء که در a1 ئه در صحت و سلامت هست، فقط دیگه در X نیست، یک ارجاع ازش کم شده، ولی همچنان همون مجموعه است که بود. نه بلایی سر خودش اومده و نه اعضاء اش. ساختارش کوچکترین تغییری نکرده. چه چیزی مربوط به شیء ای که در a1 باشه تغییر کرده که بخواد اطلاع بده؟ این به معنی تغییر مجموعه نیست که A بخواد به جایی اطلاع بده. مگه تغییر کرده که اطلاع بده؟ فرض کنید که در X ئه null قرار بگیره، بلایی سر a1 میاد؟ نه. اگر جایی بخواد تغییر رو اطلاع بده فقط و فقط خود X ئه.
برای زمانی که کل کالکشن ، به شیِ جدیدی تغییر کنه (نه اعضای کالکشن) ، میتونیم با پیاده سازیِ اینترفیس INotifyPropertyChanged ، به شیِ Binding ای که به پروپرتیِ ObservableCollection مون متصل شد ، اطلاع بدیم .
قطعا.
مثل تمام اعضای معمولی که وقتی شیِ شون تغییر میکرد (نه عضوِ خاص از اون شی) که با پیاده سازیِ اینترفیس INotifyPropertyChanged در اون پروپرتی ، میتونستیم به شیِ Binding ای که بهش متصل شد ، اطلاع بدیم .
بله.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
تفسیر درستی نیست، نمی تونه اینکار رو بکنه معنی نمیده، تغییری نمی کنه که بخواد اطلاع بده. شما از دید خود اون شیء تغییری نمی بینید که بخواد اطلاع بده. مجموعه ObservableCollection یا A یا هر نوع دیگری نمیتونه به مجموعه دیگری تغییر کرده باشه. شما با چه کدی می توانید شیء a رو به شئ دیگری تبدیل کنید؟ در #C همچین رخدادی نداریم. اصلا موضوع نوع داده خاصی مثل ObservableCollection نیست، خیلی کلی ئه، تصور کنید نوع اش ObservableCollection نیست و هر نوع دیگری باشه. وقتی شیء تغییر نمی کنه چه اطلاعی بده؟

فرضا یک نوع Collection با نام کلاس A دارید و ازش یک شیء در متغیر a1 دارید و اون شیء رو داخل مشخصه X قرار می دهید، یعنی ;X = a1
مهم نیست a1 چند تا عضو داره، مهم اینه که یک شیء ئه.
حالا یک شیء دیگر از همون نوع مجموعه A میسازید که در متغیر a2 قرار داره و در X قرار می دهید، یعنی ;X = a2
حالا مقدار X بازنویسی شده، مقدار مشخصه X تغییر کرده، به یک مجموعه دیگه اشاره می کنه، اما آیا این تغییر تاثیری روی a1 داره؟ نه. حالا چه بلایی سر اون شیء که در a1 هست اومده؟ هیچی. شیء اش تغییر کرده؟ خیر. اون شیء که در a1 ئه در صحت و سلامت هست، فقط دیگه در X نیست، یک ارجاع ازش کم شده، ولی همچنان همون مجموعه است که بود. نه بلایی سر خودش اومده و نه اعضاء اش. ساختارش کوچکترین تغییری نکرده. چه چیزی مربوط به شیء ای که در a1 باشه تغییر کرده که بخواد اطلاع بده؟ این به معنی تغییر مجموعه نیست که A بخواد به جایی اطلاع بده. مگه تغییر کرده که اطلاع بده؟ فرض کنید که در X ئه null قرار بگیره، بلایی سر a1 میاد؟ نه. اگر جایی بخواد تغییر رو اطلاع بده فقط و فقط خود X ئه.

قطعا.

بله.

خیلی ممنون استاد .
بله . ببخشید ، خود شیِ Binding ، از پیاده سازی های اینترفیس INotifyPropertyChanged که صورت گرفته ، متوجه میشه (اگه چیزهایی که گفتین را درست یادم باشه ، همین بود) .
بالاخره ، منظورم این بود که شی بایندینگ ، مطلع میشه .
تشکر استاد .
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلام
استاد ، میگم مایکروسافت انگار یه چیزی به نامِ WinUI زد که تا جایی که خوندم و فهمیدم ، مجموعه ای از کنترل ها و استایل ها و کمپوننت های مدرن هست که در نسخه ی 3 اش ، در شرایطی ، توی WPF و WinForm هم میتونه استفاده بشه و ویندوز 10 نسخه ی 1809 و بالاتر را پشتیبانی میکنه :

و
و

اما خودش ، یک پلتفرم جداگانه مثل WPF و WinForm و UWP نیست .
البته اگه در ست متوجه شده باشم نمیدونم شدم یا نه .
درباره ی رابطه اش با Fluent Design System یه کم صحبت کرد که هر چند زیاد متوجه نشدم که چیه اما این قدر فهمیدم که سیستمی برای طراحی رابط کاربری مدرن برای بصورت کراس پلتفرم میتونه باشه :



اینها انگار به SDK ای بنامِ Window App SDK وابسته هستند . (با Window SDK فرق داره) .
یه بررسی اولیه برای ریفرنس و اعضای Managed ئه Window App SDK که کردم ، انگار خیلی شبیه ریفرنس های WPF هست . ببینید :

مثلا ریفرنس های Shapes های Window App SDK :

یا ریفرنس های Media های Window App SDK :

و خیلی های دیگه اش هم شبیه اعضای WPF هستن انگار .
فرق شون پس در چیه؟
تفاوت شون در اینکه اونها از سیستم عامل جدا هستند و بسته به پلتفرمی که از اون ریفرنس ها استفاده میکنن ، اون پلتفرم میتونه چند سکویی باشه؟ اینه؟

تشکر استاد .
 
آخرین ویرایش:

the_king

مدیرکل انجمن
سلام
استاد ، میگم مایکروسافت انگار یه چیزی به نامِ WinUI زد که تا جایی که خوندم و فهمیدم ، مجموعه ای از کنترل ها و استایل ها و کمپوننت های مدرن هست که در نسخه ی 3 اش ، در شرایطی ، توی WPF و WinForm هم میتونه استفاده بشه و ویندوز 10 نسخه ی 1809 و بالاتر را پشتیبانی میکنه :

و
و

اما خودش ، یک پلتفرم جداگانه مثل WPF و WinForm و UWP نیست .
البته اگه در ست متوجه شده باشم نمیدونم شدم یا نه .
درباره ی رابطه اش با Fluent Design System یه کم صحبت کرد که هر چند زیاد متوجه نشدم که چیه اما این قدر فهمیدم که سیستمی برای طراحی رابط کاربری مدرن برای بصورت کراس پلتفرم میتونه باشه :



اینها انگار به SDK ای بنامِ Window App SDK وابسته هستند . (با Window SDK فرق داره) .
یه بررسی اولیه برای ریفرنس و اعضای Managed ئه Window App SDK که کردم ، انگار خیلی شبیه ریفرنس های WPF هست . ببینید :

مثلا ریفرنس های Shapes های Window App SDK :

یا ریفرنس های Media های Window App SDK :

و خیلی های دیگه اش هم شبیه اعضای WPF هستن انگار .
فرق شون پس در چیه؟
تفاوت شون در اینکه اونها از سیستم عامل جدا هستند و بسته به پلتفرمی که از اون ریفرنس ها استفاده میکنن ، اون پلتفرم میتونه چند سکویی باشه؟ اینه؟
اولا UWP پلتفرم پردازشی ئه، یک نوع پلتفرم برنامه است، نه پلتفرم واسط کاربری و قابل مقایسه با WPF و WinForm و WinUI نیست.
برنامه ای میسازه که علاوه بر ویندوز در سایر سیستم عامل های مایکروسافت مثل Windows 10 Mobile و Xbox One قابل اجرا باشند، ربطی به اون واسط های کاربری نداره.
ثانیا همانطوری که کنترل های WPF رو میشه با Host مبدل در فرم های WinForms قرار داد و برعکس، با قابلیت XAML Islands میشه همین کار رو برای کنترل های WinUI انجام داد، البته در ویندوز 10 به بعد.
ثالثا WinUI 2 تحت UWP ئه، بنابر این محدود به سیستم عامل ویندوز نیست. WinUI 3 هم در حال توسعه است.
رابعا Windows App SDK شامل زبان XAML برای WinUI ئه که قبلا مشابه اش با WPF ارائه شده بود، بنابر این طبیعی است که بخش عمده ای از آنچه در XAML ئه WPF دیدید در این یکی هم باشه.
فرقشون در اینه که یکی شون برای WPF ئه و دیگری برای WinUI
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
اولا UWP پلتفرم پردازشی ئه، یک نوع پلتفرم برنامه است، نه پلتفرم واسط کاربری و قابل مقایسه با WPF و WinForm و WinUI نیست.
برنامه ای میسازه که علاوه بر ویندوز در سایر سیستم عامل های مایکروسافت مثل Windows 10 Mobile و Xbox One قابل اجرا باشند، ربطی به اون واسط های کاربری نداره.
ثانیا همانطوری که کنترل های WPF رو میشه با Host مبدل در فرم های WinForms قرار داد و برعکس، با قابلیت XAML Islands میشه همین کار رو برای کنترل های WinUI انجام داد، البته در ویندوز 10 به بعد.
ثالثا WinUI 2 تحت UWP ئه، بنابر این محدود به سیستم عامل ویندوز نیست. WinUI 3 هم در حال توسعه است.
رابعا Windows App SDK شامل زبان XAML برای WinUI ئه که قبلا مشابه اش با WPF ارائه شده بود، بنابر این طبیعی است که بخش عمده ای از آنچه در XAML ئه WPF دیدید در این یکی هم باشه.
فرقشون در اینه که یکی شون برای WPF ئه و دیگری برای WinUI

سلامی مجدد
خیلی ممنون استاد .

الان ، عکس هایی که در لینک زیر هست (در قسمت Screenshots) ، کنترل هایی هستن که در WinUI 3 وجود دارن؟


یعنی این کنترل ها را میشه به wpf (اون هم در نسخه ی .Net 5 و بالاتر) و همچنین در ویندوز 10 نسخه ی 17763.0 یا بالاتر ، میشه استفاده کرد دیگه؟
انگار این WinUI 3 ، نسخه های .Net FrameWork را پشتیبانی نمیکنه .
انگار هم کنترل هاش ، به روز میشن . حالا نمیدونم فرضا قابلیت هایی بهشون افزوده میشه یا اعضای جدیدی بهشون افزوده میشه یا نه .
چون توی اون عکس (زیر) :


apps.40774.14537231059450374.fa473cce-2d15-4593-af51-d74600d35e3d.0c5fa6ae-2475-4125-a7aa-422e427b6e84



که قسمتِ whats new هست ، فرضا ComboBox (و بقیه ی کنترل ها) را کنارش زده updated .

و همچنین لینک زیر هم ، کنترل ها در همه ی نسخه های WinUI هست . درسته؟ :


و چون فقط نسخه ی WinUI 3 نیست ، و فقط از نسخه ی WinUI 3 (به بعد) میتونیم در WPF استفاده کنیم ، پس کنترل هایی که در لینک دومی گفت را نمیتونیم در WPF استفاده کنیم . درسته؟
وسعت کنترل هایی که در لینک دومی هست انگار بیشتره .

این برنامه ای که ساختن و کنترل ها را در این به نمایش گذاشتن (عکس بالا که مربوط به WinUI 3 هست) ، برنامه اش را چرا نذاشتن تا ما هم تمام کنترل هاش را بررسی کنیم؟
یا گذاشتن و من نمیدونم . اگه شما به این برنامه دسترسی دارید یا بَعدها پیدا کردین ، به من هم بگین ، ممنون میشم .

تشکر استاد .
 

جدیدترین ارسال ها

بالا