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

the_king

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

الان ، عکس هایی که در لینک زیر هست (در قسمت 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 هست) ، برنامه اش را چرا نذاشتن تا ما هم تمام کنترل هاش را بررسی کنیم؟
یا گذاشتن و من نمیدونم . اگه شما به این برنامه دسترسی دارید یا بَعدها پیدا کردین ، به من هم بگین ، ممنون میشم .

تشکر استاد .
سوالات تون ربطی به موضوع تاپیک نداره و جواب همه این سوالات رو با جستجو می توانید پیدا کنید.
هر برنامه ای که در Windows App Store ئه اونجا است تا رایگان یا پولی دریافت بشه. در مورد آموزش اش هم می توانید جستجو کنید.
 

SajjadKhati

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

اون فایل های png ای که قبلا رنگ آمیزی کردین را به پروژه ام اضافه کردم و کد زیر را در رویداد لود ویندوز نوشتم :

C#:
        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            string filePath = "pack://application:,,,/Resource/ApplicationIcon/Poshtibangir Tolo Bad.png";
            Uri uri = new Uri(filePath, UriKind.Absolute);
            BitmapImage bitmap = new BitmapImage();
            bitmap.BeginInit();
            bitmap.UriSource = uri;
            bitmap.DecodePixelWidth = 128;
            //bitmap.DecodePixelHeight = 320;
            bitmap.EndInit();

            this.Icon = bitmap;

            Hardcodet.Wpf.TaskbarNotification.TaskbarIcon taskbarIcon = new Hardcodet.Wpf.TaskbarNotification.TaskbarIcon();
            taskbarIcon.IconSource = bitmap;
        }

اگه کدهای مربوط به taskbarIcon را نمینوشتم ، درست کار میکرد اما خط آخر ارور زیر را میده :

Argument 'picture' must be a picture that can be used as a Icon.

چرا این ارور را میده؟
با پروپرتیِ taskbarIcon.Icon مقداردهی کنم؟ با این پروپرتی نمیشه؟

ضمنا ، DecodePixelWidth مگه اندازه را بر اساس پیکسل تعیین نمیکنه؟
وقتی مقدار 32 میدم ، عرض اش خیلی کوچیکتر از 32 پیکسل هست . چیزی در حد 8 پیکسل .

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

البته بماند که مقدار رشته ی uri اش را به زحمت بدست آوردم . اول مقدار Window.Icon را در xaml نوشتم و بعد با break point ، مقدار uri اش را کپی کردم . البته باز هم اندک تغییراتی دادم تا کار کرد . نمیدونم چرا uri ای که در xaml با در سی شارپ میدیم ، از هم متفاوت باید باشن!

تشکر استاد .
 

the_king

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

اون فایل های png ای که قبلا رنگ آمیزی کردین را به پروژه ام اضافه کردم و کد زیر را در رویداد لود ویندوز نوشتم :

C#:
        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            string filePath = "pack://application:,,,/Resource/ApplicationIcon/Poshtibangir Tolo Bad.png";
            Uri uri = new Uri(filePath, UriKind.Absolute);
            BitmapImage bitmap = new BitmapImage();
            bitmap.BeginInit();
            bitmap.UriSource = uri;
            bitmap.DecodePixelWidth = 128;
            //bitmap.DecodePixelHeight = 320;
            bitmap.EndInit();

            this.Icon = bitmap;

            Hardcodet.Wpf.TaskbarNotification.TaskbarIcon taskbarIcon = new Hardcodet.Wpf.TaskbarNotification.TaskbarIcon();
            taskbarIcon.IconSource = bitmap;
        }

اگه کدهای مربوط به taskbarIcon را نمینوشتم ، درست کار میکرد اما خط آخر ارور زیر را میده :



چرا این ارور را میده؟
چون به هر دلیلی نمیتونه تصویر png رو به آیکون تبدیل کنه. اصولا Icon شامل چندین تصویر در ابعاد و عمق رنگ های متفاوت ئه، نه فقط یک تصویر در یک ابعاد و عمق رنگ خاص. از نرم افزار هایی مثل Easy PNG to Icon کمک بگیرید.
ضمنا ، DecodePixelWidth مگه اندازه را بر اساس پیکسل تعیین نمیکنه؟
وقتی مقدار 32 میدم ، عرض اش خیلی کوچیکتر از 32 پیکسل هست . چیزی در حد 8 پیکسل .
نسبت افقی به عمودی در PNG تون (aspect ratio) ایراد داره، طول و عرض تصویر برابر ئه؟ حالا یا از اول با ابعاد نادرست طراحی اش کرده اید یا در هنگام دکود شدن نسبت طول به عرض تغییر کرده.
البته بماند که مقدار رشته ی uri اش را به زحمت بدست آوردم . اول مقدار Window.Icon را در xaml نوشتم و بعد با break point ، مقدار uri اش را کپی کردم . البته باز هم اندک تغییراتی دادم تا کار کرد . نمیدونم چرا uri ای که در xaml با در سی شارپ میدیم ، از هم متفاوت باید باشن!
چون موقعیت Resource ها در Pack URI بر اساس مسیر بعد از کامپایل تعیین میشه، فرضا موقعی که اون تصویر در Resources فایل اجرایی ادغام شده. اما در XAML دارید قبل از زمان کامپایل به مسیری ارجاع می دهید که در Resources پروژه قابل دسترسی است، نه یک فایل اجرایی.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
چون به هر دلیلی نمیتونه تصویر png رو به آیکون تبدیل کنه. اصولا Icon شامل چندین تصویر در ابعاد و عمق رنگ های متفاوت ئه، نه فقط یک تصویر در یک ابعاد و عمق رنگ خاص. از نرم افزار هایی مثل Easy PNG to Icon کمک بگیرید.

خیلی ممنون استاد .
بله . بخاطر همین بود .
ولی وقتی یه شی از BitmapImage که درست کردیم ، اطلاعاتش توی رم لود میشه دیگه .
بعد از اون که دیگه از اطلاعات فایل png که استفاده نمیکنه . مگه استفاده میکنه؟!
پس چرا باز این ارور را خط آخر (در taskbarIcon.IconSource) داد؟!
معنا نداره وقتی اطلاعاتی در رم لود شد ، باز وابسته به فایل png باشه .

از فایل با پسوند icon نمیخوام استفاده کنم . چون کیفیت اش نسبت به png ایین میاد . شما میدونید چجوری بدون افت کیفیت ، تبدیل به فایل با پسوند ico کنیم؟
من که تست کرده بودم ، یه کم انگار کیفیت اش پایین میمومد .

نسبت افقی به عمودی در PNG تون (aspect ratio) ایراد داره، طول و عرض تصویر برابر ئه؟

بله ، برابر هست .

حالا یا از اول با ابعاد نادرست طراحی اش کرده اید یا در هنگام دکود شدن نسبت طول به عرض تغییر کرده.

همون فایلی هست که در تاپیک "درخواست طراحی آیکون" برام زحمتش را کشیدید . همون ابعاد (32 در 32) و ... . عمق رنگ شون هم 64 بود و هست .

چون موقعیت Resource ها در Pack URI بر اساس مسیر بعد از کامپایل تعیین میشه، فرضا موقعی که اون تصویر در Resources فایل اجرایی ادغام شده. اما در XAML دارید قبل از زمان کامپایل به مسیری ارجاع می دهید که در Resources پروژه قابل دسترسی است، نه یک فایل اجرایی.

آها خیلی ممنون .
استاد ، آیا میشه مسیری که برای uri ای که در کد پست 862 هست (متغییر filePath) ، استفاده میکنیم را به آدرسی تبدیل کنیم که بشه در کلاس System.Drawing.Bitmap ارش استفاده کرد؟
منظورم در آرگومانِ filename ئه متدِ سازنده ی System.Drawing.Bitmap هست :


چون اون آدرسِ uri ، آدرسِ فایلِ png ای هست که درونِ پوشه ای به عنوان ریسورسِ پروژه ام هست . یعنی داخل پوشه ی برنامه ام نیست و نمیخوام زمانی که برنامه ام را منتشر میکنم ، اون فایل های png ، همراه برنامه ام باشه . یعنی اون فایل ها درون پوشه ی bin در برنامه ام نیست و برای همین منتشر نمیشه .

یا کلا آیا میشه آدرس فایلی که درون ریسورسِ برنامه هست (ولی به همراه برنامه منتشر نمیشه) را به متد سازنده ی System.Drawing.Bitmap داد؟
اگه آره ، چجوری؟

تشکر استاد .
 

the_king

مدیرکل انجمن
خیلی ممنون استاد .
بله . بخاطر همین بود .
ولی وقتی یه شی از BitmapImage که درست کردیم ، اطلاعاتش توی رم لود میشه دیگه .
بعد از اون که دیگه از اطلاعات فایل png که استفاده نمیکنه . مگه استفاده میکنه؟!
فرقی نمی کنه، همون داده است، تغییر فرمت که نمیده.
پس چرا باز این ارور را خط آخر (در taskbarIcon.IconSource) داد؟!
معنا نداره وقتی اطلاعاتی در رم لود شد ، باز وابسته به فایل png باشه .
صحبت وابستگی به فایل نیست.
از فایل با پسوند icon نمیخوام استفاده کنم . چون کیفیت اش نسبت به png ایین میاد . شما میدونید چجوری بدون افت کیفیت ، تبدیل به فایل با پسوند ico کنیم؟
آیکون محدودیت اش در ابعادشه که ربطی به نرم افزار نداره. موقع طراحی آیکون برای ابعاد کوچک باید طرحی رو بکار ببرید که جزئیاتش در حد اون ابعاد باشه.
همون فایلی هست که در تاپیک "درخواست طراحی آیکون" برام زحمتش را کشیدید . همون ابعاد (32 در 32) و ... . عمق رنگ شون هم 64 بود و هست .
عمق رنگ 64؟ 64 بیتی یا 64 رنگی؟ تصاویر منبع برای آیکون سازی رو 32 بیتی در نظر بگیرید.
آها خیلی ممنون .
استاد ، آیا میشه مسیری که برای uri ای که در کد پست 862 هست (متغییر filePath) ، استفاده میکنیم را به آدرسی تبدیل کنیم که بشه در کلاس System.Drawing.Bitmap ارش استفاده کرد؟
منظورم در آرگومانِ filename ئه متدِ سازنده ی System.Drawing.Bitmap هست :


چون اون آدرسِ uri ، آدرسِ فایلِ png ای هست که درونِ پوشه ای به عنوان ریسورسِ پروژه ام هست . یعنی داخل پوشه ی برنامه ام نیست و نمیخوام زمانی که برنامه ام را منتشر میکنم ، اون فایل های png ، همراه برنامه ام باشه . یعنی اون فایل ها درون پوشه ی bin در برنامه ام نیست و برای همین منتشر نمیشه .

یا کلا آیا میشه آدرس فایلی که درون ریسورسِ برنامه هست (ولی به همراه برنامه منتشر نمیشه) را به متد سازنده ی System.Drawing.Bitmap داد؟
اگه آره ، چجوری؟
چرا قبل سوال جستجو نمی کنید؟
C#:
            var resourceStream = System.Windows.Application.GetResourceStream(new Uri("/image.png", UriKind.Relative));
            var image = System.Drawing.Image.FromStream(resourceStream.Stream);
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
فرقی نمی کنه، همون داده است، تغییر فرمت که نمیده.
صحبت وابستگی به فایل نیست.

خیلی ممنون استاد .
یعنی با همون فرمت و کدک ، عینا توی رم لود میکنن؟
قبلش decode نمیکنن و decode شده را توی رم لود نمیکنن؟

آیکون محدودیت اش در ابعادشه که ربطی به نرم افزار نداره. موقع طراحی آیکون برای ابعاد کوچک باید طرحی رو بکار ببرید که جزئیاتش در حد اون ابعاد باشه.

از طریق سایت های آنلاین تبدیل کردم که کیفیتش خوبه . اما از طریق نرم افزارهای آفلاین (که توی سیستم نصب میکردم) ، کیفیت خروجی اش خوب در نمیومد .

عمق رنگ 64؟ 64 بیتی یا 64 رنگی؟ تصاویر منبع برای آیکون سازی رو 32 بیتی در نظر بگیرید.

ببخشید ، عمق بیت شون .
نمیدونم چیه.
کلیک راست که روی تصویر میکنم و Properties>Details ، مقدار Bit Depth اش را 64 نوشته که وقتی تبدیل به ico میکنم 32 میشه .

بیت های هر کانال از رنگ که فکر نکنم باشه . چون هر کانالِ رنگ اگه 8 بیت هم باشن و 4 کانال هم باشن (argb) ، کلا 32 بیت میشه و 16 و خردی میلیون رنگ توش جا میشه دیگه (از 16 و خردی میلیون به بالاتر رنگ مگه وجود داره؟) .

چرا قبل سوال جستجو نمی کنید؟
C#:
            var resourceStream = System.Windows.Application.GetResourceStream(new Uri("/image.png", UriKind.Relative));
            var image = System.Drawing.Image.FromStream(resourceStream.Stream);

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

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

--------

بعد اینکه استاد ، میشه شیِ BitmapImage را به شیِ Geomerty (منظورم System.Windows.Media.Geometry هست) یا به شیِ Path (منظورم System.Windows.Shapes.Path هست) تبدیل کرد؟
جستو کردم .

تشکر استاد .
 

the_king

مدیرکل انجمن
خیلی ممنون استاد .
یعنی با همون فرمت و کدک ، عینا توی رم لود میکنن؟
قبلش decode نمیکنن و decode شده را توی رم لود نمیکنن؟
به وسیله BitmapDecoder خونده یا دانلود و کدگشایی میشه و BitmapFrame و مسیر منبع اش در حافظه Cache قرار می گیره.
از طریق سایت های آنلاین تبدیل کردم که کیفیتش خوبه . اما از طریق نرم افزارهای آفلاین (که توی سیستم نصب میکردم) ، کیفیت خروجی اش خوب در نمیومد .

ببخشید ، عمق بیت شون .
نمیدونم چیه.
کلیک راست که روی تصویر میکنم و Properties>Details ، مقدار Bit Depth اش را 64 نوشته که وقتی تبدیل به ico میکنم 32 میشه.
بیت های هر کانال از رنگ که فکر نکنم باشه . چون هر کانالِ رنگ اگه 8 بیت هم باشن و 4 کانال هم باشن (argb) ، کلا 32 بیت میشه و 16 و خردی میلیون رنگ توش جا میشه دیگه (از 16 و خردی میلیون به بالاتر رنگ مگه وجود داره؟) .
عمق رنگ عادی نیست، هر کانال رنگی اش 16 بیتی ئه، چهار تا 16 بیتی، 16 * 4 = 64.
خیلی ممنون
یادم میاد قبلا گفته بودین که Stream برای چیزهایی کاربرد داره که بصورت جریانی و مستمر بخواد استفاده بشه . مثلا وقتی که یه پلیر ، میخواد فایلی را بخونه یا چیزی را ضبط کنیم و دانلود کنیم و ... .
بجز این موارد ، چجوری متوجه شدین که در این مورد ، Stream بکار میاد و میشه ازش استفاده کرد؟
اگه ورودی و خروجی های مبدل ها و منابع رو در NET. ببینید، اغلب با Stream کار می کنند.
میتونم این نتیجه را بگیرم که بجز این موارد ، برای تبدیل هم ، اگه ، هم نوع مبدا ، و هم نوع مقصد از Stream پشتیبانی کردن (که نمیدونم چه انواعی پشتیبانی میکنن) ، میشه از Stream برای تبدیل هم استفاده کرد؟
بله، فقط در نظر بگیرید که هر شی Stream از هر طریقی که تامین شده باشه، یکسری ویژگی داره که نشون میده با اون منبع چه کاری میشه کرد و چه کاری نمی شه. فرضا CanRead و CanSeek و CanWrite داره که میگه میشه ازش خوند، میشه طولش رو بدست آورد، میشه در بین داده ها جلو و عقب کرد و از جاهای مختلف داده رو مجددا خوند و نوشت و ...
ممکنه در یک روال ازتون فقط Stream ای قبول کنه که CanSeek اش حتما true باشه، چون فرضا بدون اون نمیتونه طول Stream رو بدونه و لازمش داره. پس اگر Stream ای بهش بدهید که طول داده اش نامعلوم باشه یا نشه موقعیت اش رو جلو و عقب کرد، این Stream ئه CanSeek شدنی نیست و اون روتین نمیتونه باهاش کار کنه.
بعد اینکه استاد ، میشه شیِ BitmapImage را به شیِ Geomerty (منظورم System.Windows.Media.Geometry هست) یا به شیِ Path (منظورم System.Windows.Shapes.Path هست) تبدیل کرد؟
شدنش که حتما میشه، اما باید برای نوشتنش وقت صرف کنید. نیاز به کتابخانه مجهزی داره چون پردازش پیچیده ای داره، اصولا اینکار وظیفه نرم افزاری طراحی برداری مجهز ئه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
به وسیله BitmapDecoder خونده یا دانلود و کدگشایی میشه و BitmapFrame و مسیر منبع اش در حافظه Cache قرار می گیره.

عمق رنگ عادی نیست، هر کانال رنگی اش 16 بیتی ئه، چهار تا 16 بیتی، 16 * 4 = 64.

اگه ورودی و خروجی های مبدل ها و منابع رو در NET. ببینید، اغلب با Stream کار می کنند.

بله، فقط در نظر بگیرید که هر شی Stream از هر طریقی که تامین شده باشه، یکسری ویژگی داره که نشون میده با اون منبع چه کاری میشه کرد و چه کاری نمی شه. فرضا CanRead و CanSeek و CanWrite داره که میگه میشه ازش خوند، میشه طولش رو بدست آورد، میشه در بین داده ها جلو و عقب کرد و از جاهای مختلف داده رو مجددا خوند و نوشت و ...
ممکنه در یک روال ازتون فقط Stream ای قبول کنه که CanSeek اش حتما true باشه، چون فرضا بدون اون نمیتونه طول Stream رو بدونه و لازمش داره. پس اگر Stream ای بهش بدهید که طول داده اش نامعلوم باشه یا نشه موقعیت اش رو جلو و عقب کرد، این Stream ئه CanSeek شدنی نیست و اون روتین نمیتونه باهاش کار کنه.

سلامی مجدد
خیلی ممنون استاد از توضیحات تون

شدنش که حتما میشه، اما باید برای نوشتنش وقت صرف کنید. نیاز به کتابخانه مجهزی داره چون پردازش پیچیده ای داره، اصولا اینکار وظیفه نرم افزاری طراحی برداری مجهز ئه.

سناریو ام اینه :
من یه user control دارم که یه کنترلِ سفارشیِ shape text button داره که این کنترل ، یه شیِ path (که شامل Data و Geometry هست) را استفاده میکنه . چون شکل هایی که تا حالا استفاده میکردم ، بر اساس vector گرافیک بوده ، مشکلی نبوده .

اما الان میخوام در یکی از شیِ این user control ، در اون کنترلِ shape text button ، از همون vector گرافیک استفاده کنم (در ویندوزِ تنظیمات) اما در یک شیِ دیگه از user control ، در اون کنترلِ shape text button ، از اون فایلِ ico که شما طراحی کرده بودین استفاده کنم (در ویندوزِ اصلی) .

مشکل اینجاست که shape text button ، چون جوری طراحی شد که نوع path را قبول میکنه ، به درد گرافیک های بیت مپی نمیخوره (زمان طراحی فکر نمیکردم که از گرافیک های پیکسلی هم استفاده کنم) .

حالا فکر میکنم که بجای shape text button ، از کنترل Image (منظورم System.Windows.Controls.Image هست) استفاده کنم ؛ که Source اش ، نوعِ ImageSource را میخواد که مناسبِ گرافیک های پیکسلی مثل فایل ico هست اما مناسبِ گرافیک های vector نیست .

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

کنترلی هست که بشه هم توش گرافیک های پیکسلی و هم vector گرافیک را رسم کرد؟
کلا برای این سناریو ، پیشنهادی دارین؟

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

the_king

مدیرکل انجمن
سلامی مجدد
خیلی ممنون استاد از توضیحات تون



سناریو ام اینه :
من یه user control دارم که یه کنترلِ سفارشیِ shape text button داره که این کنترل ، یه شیِ path (که شامل Data و Geometry هست) را استفاده میکنه . چون شکل هایی که تا حالا استفاده میکردم ، بر اساس vector گرافیک بوده ، مشکلی نبوده .

اما الان میخوام در یکی از شیِ این user control ، در اون کنترلِ shape text button ، از همون vector گرافیک استفاده کنم (در ویندوزِ تنظیمات) اما در یک شیِ دیگه از user control ، در اون کنترلِ shape text button ، از اون فایلِ ico که شما طراحی کرده بودین استفاده کنم (در ویندوزِ اصلی) .

مشکل اینجاست که shape text button ، چون جوری طراحی شد که نوع path را قبول میکنه ، به درد گرافیک های بیت مپی نمیخوره (زمان طراحی فکر نمیکردم که از گرافیک های پیکسلی هم استفاده کنم) .

حالا فکر میکنم که بجای shape text button ، از کنترل Image (منظورم System.Windows.Controls.Image هست) استفاده کنم ؛ که Source اش ، نوعِ ImageSource را میخواد که مناسبِ گرافیک های پیکسلی مثل فایل ico هست اما مناسبِ گرافیک های vector نیست .

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

کنترلی هست که بشه هم توش گرافیک های پیکسلی و هم vector گرافیک را رسم کرد؟
کلا برای این سناریو ، پیشنهادی دارین؟

تشکر استاد .
قبلا گفتم که Bitmap برای رسم در WPF مناسب نیست، از طرف دیگه shape text button بر اساس الگوی کنترل های فرم ویندوز طراحی شده، نه سبک طراحی WPF. در WPF اجزاء می توانند به سادگی از ترکیب اجزاء دیگه توصیف بشوند، برای همین برای اینکارا نیازی به تعریف مشخصه A و B نیست.
یک Button در WPF میتونه شامل چندین المنت داخلی باشه، بدون اینکه در کلاس Button برای هر کدوم مشخصه و تنظیماتی اختصاص داده بشه.
طراح میتونه بدون نیاز به وجود ساختار کنترل خاصی چندین منحنی و تصاویر رو بصورت یک تصویر ترکیبی در المنت مورد نظرش نمایش بده و نیازی به کمپوننت نداره.
XML:
    <Grid>
        <Image>
            <Image.Source>
                <DrawingImage>
                    <DrawingImage.Drawing>
                        <DrawingGroup>
                            <GeometryDrawing Brush="#66B5F314">
                                <GeometryDrawing.Geometry>
                                    <EllipseGeometry Center="50,50" RadiusX="50"  RadiusY="50"/>
                                </GeometryDrawing.Geometry>
                                <GeometryDrawing.Pen>
                                    <Pen Brush="Black" Thickness="4" />
                                </GeometryDrawing.Pen>
                            </GeometryDrawing>
                            <ImageDrawing ImageSource="image.png" Rect="50,50,100,100"/>
                            <GeometryDrawing Brush="#66B5F314">
                                <GeometryDrawing.Geometry>
                                    <EllipseGeometry Center="150,150" RadiusX="50"  RadiusY="50"/>
                                </GeometryDrawing.Geometry>
                                <GeometryDrawing.Pen>
                                    <Pen Brush="Black" Thickness="4" />
                                </GeometryDrawing.Pen>
                            </GeometryDrawing>
                        </DrawingGroup>
                    </DrawingImage.Drawing>
                </DrawingImage>
            </Image.Source>
        </Image>
    </Grid>
 

SajjadKhati

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

- وقتی یه پروپرتی را Binding میکنیم ، اگه Binding Target Property را مجددا به شی ای از مقدار صریحی تعیین کنیم (یعنی از هر نوع پروپرتی ای که هست ، همون شی را بدیم) ، دیگه بهش Binding تعلق نمیگیره ، یعنی با تغییر مقدار پروپرتیِ Binding Source Property ، دیگه مقدار Binding Target Property ، تغییری نمیکنه و اون مقدار صریحی که برای Binding Source Property ، در نظر گرفتیم ، اِعمال میشه (که تقریبا معلوم بود . حالا به عنوان نکته ی کوچیک گفتم) .


- یادآوری این نکته که قبلا گفته بودین ، خوبه و اون اینکه برای اینکه شیِ Binding از تغییر مقدار مطلع بشه ، یا اینترفیس INotifyPropertyChanged و رویداد PropertyChanged در اون پروپرتی باید فراخونی بشه و یا اینکه اون پروپرتی باید از نوع DependencyProperty باشه .
یه کدوم از اینها باید باشه . نباید دو تا با هم باشن . یعنی نمیشه DependencyProperty ای تعریف کنیم و در قسمت set اش ، رویداد PropertyChanged را فراخونی کنیم . شدن که میشه ، فایده نداره . چون wpf برای مقداردهی ، از قسمت set ئه پروپرتی ما (clr) استفاده نمیکنه . مستقیما متد SetValue را فراخونی میکنه .


- نکته ی دیگه اینکه وقتی فرضا در پروپرتی Background ئه یه Button ، یه Binding ای انجام میدیم و مینویسیم :

XML:
        <Button  Background="{Binding RelativeSource={RelativeSource Mode=Self}}">

در این کد ، منظور از Self ، خودِ شیِ Button هست (که داریم برای پروپرتیِ Background اش کد Binding مینویسیم) .
منظور ، شیِ Window ای که اون Button توش هست ، نیست .

که البته بعضی از این نکات را هم قبا گفته بودین .
تشکر
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلامی مجدد
استاد ، در یه کلاس از Model مون ، یه پروپرتی (فرضا بنام A) از نوعِ یه Enum (ای که اون Enum را هم در Model مون تعریف کردیم) ، تعریف کردیم .
حالا بر اساس مقدارِ Enum ای که اون پروپرتی ، برمیگردونه ، میخوام یه پروپرتیِ دیگه (فرضا بنام B) ، همون را بصورت رشته برگردونه .
بعد هم میخوام یه پروپرتیِ View را به پروپرتیِ B (که از نوع رشته بود) ، Binding کنم .


حالا این تبدیل نوع (تبدیل Enum به رشته) ، در کدوم لایه انجام بشه ، اصولی تر هست؟ در لایه ی Model تبدیل بشه یا در لایه ی ViewModel تبدیل بشه ، اصولی تر هست؟
کلا کار تبدیل ، بر عهده ی کدوم لایه هست؟
خودم حس میکنم وظیفه ی لایه ی ViewModel باشه . درسته؟

یعنی پروپرتیِ A که در Model تعریف شد ، پروپرتیِ B (که تبدیل شده ی پروپرتیِ A ، به نوع رشته هست) ، در لایه ی ViewModel تعریف بشه ، اصولی تر هست . درست میگم؟
تشکر استاد .
 

the_king

مدیرکل انجمن
سلامی مجدد
استاد ، در یه کلاس از Model مون ، یه پروپرتی (فرضا بنام A) از نوعِ یه Enum (ای که اون Enum را هم در Model مون تعریف کردیم) ، تعریف کردیم .
حالا بر اساس مقدارِ Enum ای که اون پروپرتی ، برمیگردونه ، میخوام یه پروپرتیِ دیگه (فرضا بنام B) ، همون را بصورت رشته برگردونه .
بعد هم میخوام یه پروپرتیِ View را به پروپرتیِ B (که از نوع رشته بود) ، Binding کنم .


حالا این تبدیل نوع (تبدیل Enum به رشته) ، در کدوم لایه انجام بشه ، اصولی تر هست؟ در لایه ی Model تبدیل بشه یا در لایه ی ViewModel تبدیل بشه ، اصولی تر هست؟
کلا کار تبدیل ، بر عهده ی کدوم لایه هست؟
خودم حس میکنم وظیفه ی لایه ی ViewModel باشه . درسته؟

یعنی پروپرتیِ A که در Model تعریف شد ، پروپرتیِ B (که تبدیل شده ی پروپرتیِ A ، به نوع رشته هست) ، در لایه ی ViewModel تعریف بشه ، اصولی تر هست . درست میگم؟
تشکر استاد .
اصولی در این قضیه نمی بینم. اصولی تر که معنی نداره، نمیشه که چیزی اصولی باشه ولی از مورد دیگری کمتر یا بیشتر اصولی باشه.
تبدیل شی به رشته اگه روال مخصوصی داره که باید برایش کد بنویسید، وظیفه همون کلاس در Model میشه، فرضا اگر قراره RightToLeft.Yes به "Right to Left" و RightToLeft.No به "Left to Right" تبدیل بشه، ToString همچین کاری رو بصورت پیشفرض انجام نمیده. یعنی یک روال اختصاصی میخواد و طبعا جای مناسبش همون کلاس ئه که enum ئه رو تعریف کرده.

اما اگر تبدیل یک روال مخصوصی نیست، فرضا با همون ToString پیشفرض انجام اش می دهید، اونوقت دیگه الزامی نیست که در همون کلاس برایش روالی در نظر گرفته بشه، چون هر جایی میشه object رو به string تبدیل کرد. گر چه اگر در خود کلاس هم بود ایرادی نداشت.
مثلا تبدیل RightToLeft.Yes به "Yes" و تبدیل RightToLeft.No به "No" رو خود روال پیشفرض Enum انجام میده، روال اختصاصی نمیخواد.
در ضمن این روالی است که اگر در اون کلاس نوشته نشه هم چیزی از قابلیت های اون کلاس کم نکرده، بود و نبودش فرقی نمی کنه.
اینجا دیگه اهمیتی نداره که تبدیل به string رو در Model انجام می دهید یا در ViewModel یا حتی View (به شرطی که داده رو بصورت object به View برسانید).
در چنین حالتی علاوه بر دو گزینه تبدیل به string در خود کلاس یا در ViewModel، در گزینه سوم می توانید در ViewModel داده رو تبدیل به object کنید و بعد در View از روال پیشفرض تبدیل ToString چه ضمنی و چه صریح برای تبدیل object به string استفاده کنید. یعنی سه گزینه برای انتخاب دارید که مزیتی نسبت به هم ندارند.
 

SajjadKhati

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

جریان این طوره که اون پروپرتی ای که توی Model ام هست (بنام پروپرتیِ BackupStatus) و از نوعِ Enum ئه BackupStatus و در کلاسِ PoshtibangirToloBusinessLogic تعریف شده که هر دوی این کلاس و Enum ، در همون Model ام تعریف شده .
این اینام ، 3 مقدارِ Normal و Bad و Critical داره که به تناسب وضعیت بکاپ در درایوها ، یکی از این 3 مقدار ، انتخاب میشه .

به تناسبِ این انتخاب در Model ، بخشی از نام آیکون در View ام که تغییر میکنه ، همین مقدار هست (بقیه ی قسمت از نام هاشون ثابت هست) که به این ترتیب ، باید اون آیکون انتخاب بشه و برای شیِ Image در نظر گرفته بشه . یعنی نهایتا باید یه شیِ ImageSource بصورت خروجی تحویل داده بشه .

یعنی پروپرتیِ BackupStatus باید اول به رشته بصورت زیر تبدیل بشه :

C#:
string uriPath = "pack://application:,,,/Resource/ApplicationIcon/Poshtibangir Tolo " + BackupStatus.ToString() + ".ico";

بعد ، از این رشته ، شیِ uri ساخته بشه و نهایتا از این شیِ uri ، شیِ ImageSource ساخته بشه .
یعنی در چند مرحله ، شیِ نوعِ BackupStatus ، به شیِ ImageSource تبدیل بشه .
بعد هم اون پروپرتی ای که از نوع ImageSource هست ، به عنوان Binding Source استفاده میشه .

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

از اونجایی هم که منطق تجاری (Model) ئه پروژه ام (همون کلاس PoshtibangirToloBusinessLogic) ربطی بهش نداره که اطلاعاتِ رشته ی uriPath که مربوط به View هست را بدونه ، پس تبدیلِ پروپرتیِ BackupStatus به رشته ی uriPath را به لایه ی ViewModel یا لایه ی View میسپارم .
درست میگم؟

اما نکته و سئوال اینجاست که این پروپرتی از نوعِ ImageSource (که قراره به عنوان Binding Source Property ازش استفاده بشه) ، در لایه ی ViewModel تعریف بشه یا در لایه ی View؟
ظاهر امر این طوره که بهتره در View تعریف بشه اما اینجا یه پرسش مطرح میشه که شاید تعیین کنه که این پروپرتی در کدوم لایه تعریف بشه .


اون پرسش هم اینکه DataContext ئه کنترل های View ام را چی بگیرم؟ شی ای از لایه ی View بگیرم یا ViewModel بگیرم؟
چون اینکه DataContext ئه یه سری از کنترل ها ، شی ای از لایه ی View باشه و DataContext ئه یه سری از کنترل های دیگه ، شی ای از لایه ی ViewModel باشه ، باعث میشه خوانایی کد و درک کد برای ویرایش های بعدی ، سخت بشه .
بنابراین DataContext ئه کنترل ها ، همه بصورت یکپارچه ، یکی باشه ، بهتر نیست؟

تشکر استاد . :rose:
 

SajjadKhati

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

تشکر استاد . :rose:

سلامی مجدد
استاد ، پس اون ImageSource را که وظیفه ی View هست را توی View تعریف میکنم .

برای قضیه ی DataContext ، اول میذارم اعضا و پروپرتی های View و ViewModel بیشتر بشن و بعد چک میکنم که آیا به لایه ی View بیشتر از ViewModel ام Binding شده هست یا به لایه ی ViewModel (و از اون طریق به Model) .
بر این اساس ، DataContext ئه Window (و به طبع اون ، کنترل های فرزندانش) را ، شی ای از اون لایه (شی ای از کلاس View یا ViewModel) در نظر میگیرم .
فرضا اگه پروپرتی های View ام بیشتر بهش Binding بشه ، DataContext ئه Window را شیِ اون کلاسِ View میگیرم .

فرضا اما اگه علاوه بر این ، کنترل هایی بودن که به ViewModel و یا Model ام Binding شدن ، دیگه DataContext ئه اون کنترل را ست نمیکنم (چون خوانایی کد کم میشه و گمراه کننده میشه) . بلکه بجاش ، Source ئه شیِ Binding ام را مشخص میکنم . تا خوانایی اش بهتر بشه .
این کار بهتر نیست؟

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

نکته ی دیگه اینکه هر چند اون Enum را با متد object.ToString هم میشه به رشته تبدیل کرد اما چون پروپرتی ای که در Model تعریف شده هست ، از نوع Enum هست و پروپرتی ای که در View تعریف شده هست ، از نوع ImageSuorce هست ، پس نمیشه این دو پروپتری را با هم Binding کرد (مگر اینکه یه کلاسِ Converter درست کنم که نمیخوام این کار را کنم . چون زیاد شدن کلاس را برای کارهای کوچیک ، ترجیح نمیدم) .

پس باید رویداد PropertyChanger ئه Model را استفاده کنیم (مقدار این رویداد را در متد سازنده ی کلاس Model ام میگیرم چون در متد سازنده ، احتمالا مقدار پروپرتی هایی را تغییر میدم) .
به این رویداد هم که نمیتونم از View دسترسی داشته باشم .
پس ، از ViewModel ، دلیگیتی را به عنوانِ مقدارِ رویدادِ PropertyChanger ئه Model تعیین میکنم . هر وقت اون دلیگیتِ ViewModel اجرا شد ، متدِ RaisePropertyChanger ای که در ViewModel هست را اجرا میکنم تا به لایه ی View اطلاع بده.
این روش خوبه دیگه؟

تشکر استاد .
 

the_king

مدیرکل انجمن
سلامی مجدد
استاد ، پس اون ImageSource را که وظیفه ی View هست را توی View تعریف میکنم .

برای قضیه ی DataContext ، اول میذارم اعضا و پروپرتی های View و ViewModel بیشتر بشن و بعد چک میکنم که آیا به لایه ی View بیشتر از ViewModel ام Binding شده هست یا به لایه ی ViewModel (و از اون طریق به Model) .
بر این اساس ، DataContext ئه Window (و به طبع اون ، کنترل های فرزندانش) را ، شی ای از اون لایه (شی ای از کلاس View یا ViewModel) در نظر میگیرم .
فرضا اگه پروپرتی های View ام بیشتر بهش Binding بشه ، DataContext ئه Window را شیِ اون کلاسِ View میگیرم .

فرضا اما اگه علاوه بر این ، کنترل هایی بودن که به ViewModel و یا Model ام Binding شدن ، دیگه DataContext ئه اون کنترل را ست نمیکنم (چون خوانایی کد کم میشه و گمراه کننده میشه) . بلکه بجاش ، Source ئه شیِ Binding ام را مشخص میکنم . تا خوانایی اش بهتر بشه .
این کار بهتر نیست؟
نمیدونم بر چه اساسی میگید فلان کار بهتره یا خوانایی اش کم میشه. قاعده کلی ای نداره که بخواهم توصیه کنم.
نکته ی دیگه اینکه هر چند اون Enum را با متد object.ToString هم میشه به رشته تبدیل کرد اما چون پروپرتی ای که در Model تعریف شده هست ، از نوع Enum هست و پروپرتی ای که در View تعریف شده هست ، از نوع ImageSuorce هست ، پس نمیشه این دو پروپتری را با هم Binding کرد (مگر اینکه یه کلاسِ Converter درست کنم که نمیخوام این کار را کنم . چون زیاد شدن کلاس را برای کارهای کوچیک ، ترجیح نمیدم) .
پس باید رویداد PropertyChanger ئه Model را استفاده کنیم (مقدار این رویداد را در متد سازنده ی کلاس Model ام میگیرم چون در متد سازنده ، احتمالا مقدار پروپرتی هایی را تغییر میدم) .

به این رویداد هم که نمیتونم از View دسترسی داشته باشم .
پس ، از ViewModel ، دلیگیتی را به عنوانِ مقدارِ رویدادِ PropertyChanger ئه Model تعیین میکنم . هر وقت اون دلیگیتِ ViewModel اجرا شد ، متدِ RaisePropertyChanger ای که در ViewModel هست را اجرا میکنم تا به لایه ی View اطلاع بده.
این روش خوبه دیگه؟
بایدی وجود نداره، چیزی رو از ViewModel به View منتقل کنید که در View لازمه. اسم PropertyChanger رو هم خودتون اختراع کرده اید.
اون مشخصه رو برای چی می سازید؟ برای اینکه یا مقدارش رو مستقل از سایر مقادیر تغییر بدهید و یا بخواهید به منبعی Bind کنید.
اولا شما نمی خواهید مقدار ImageSource رو مستقلا تغییر بدهید، چون میخواهید بر اساس مقدار اون Enum ئه تعیین بشه.
ثانیا منبعی ندارید که بهتون ImageSource تحویل بده و بخواهید بهش Bind کنید، پس برای چی دارید مشخصه می سازید؟
اگر قراره ImageSource ئه فقط داخل خود View استفاده بشه مشخصه اش برای چیه؟ از بیرون بهش ImageSource میرسه؟

اگر قراره مقدار ImageSource ئه وابسته به Enum باشه و ImageSource ئه توسط کدی در View ایجاد بشه و بعد در المنت های View نمایش داده بشه، چرا دیگه اصلا برای ImageSource ئه مشخصه تعریف می کنید؟ برای مقدار string یا object اون Enum ئه مشخصه بسازید. همون موقع که مقدار string یا object اون Enum رو در یک مشخصه View دریافت کردید ImageSource رو بسازید و بی واسطه در المنت مورد نظر قرار بدهید.

طبعا هم وقتی مقدار enum تغییر بکنه، رابط در ViewModel هم به واسطه INotifyPropertyChanged مطلع میشه و مقدار جدیدی منتقل می کنه، Binding ای که مقدارش رو به View منتقل می کنه به View اطلاع میده و نیازی به اتصال دستی متد به رخداد PropertyChanged نیست.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بایدی وجود نداره، چیزی رو از ViewModel به View منتقل کنید که در View لازمه.

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

نوع ImageSource که طبق چیزی که گفته بودین ، به View مربوط میشه (پروپرتی اش در View تعریف میشه) .
اطلاعات BackupStatus هم که در پروپرتی ای در Model تعریف میشه .
از Converter هم که برای بایندینگ فعلا نمیخوام استفاده کنم .
پس لازمه اطلاعات تغییرِ شیِ پروپرتیِ نوعِ BackupStatus ، از Model به ViewModel و بعد به View منتقل بشه دیگه؟


اسم PropertyChanger رو هم خودتون اختراع کرده اید.

اشتباه تایپی بود .

اون مشخصه رو برای چی می سازید؟ برای اینکه یا مقدارش رو مستقل از سایر مقادیر تغییر بدهید و یا بخواهید به منبعی Bind کنید.

منظورتون پروپرتیِ نوعِ ImageSource هست؟
اگه آره ، برای اینکه این پروپرتی را به عنوان Binding Source Property برای پروپرتیِ ImageSource ئه شیِ ImageDrawing (که در شیِ Image استفاده میشه) ، استفاده کنم و بهش Binding کنم .

خودِ این پروپرتی (از نوعِ ImageSource که در View تعریف شده هست) ، با تغییرِ مقدارِ پروپرتیِ نوعِ BackupStatus (که در Model تعریف شد) ، تغییر میکنه . اما چون نوع این دو پروپرتی با هم متفاوت هستن (یکی از نوع BackupStatus و یکی هم از نوع ImageSource) ، و چون حداقل تا الان نمیخوام از Converter برای بایندینگ شون استفاده کنم ، پس نمیتونم این دو پروپرتی را با هم Binding کنم .

اولا شما نمی خواهید مقدار ImageSource رو مستقلا تغییر بدهید، چون میخواهید بر اساس مقدار اون Enum ئه تعیین بشه.

بله . همینطوره .

ثانیا منبعی ندارید که بهتون ImageSource تحویل بده و بخواهید بهش Bind کنید،

بله . درسته (چون حداقل تا الان نمیخوام از converter استفاده کنم) .

در پرانتز اینو بگم که مایکروسافت برای استفاده از converter در Binding ، بجای استفاده از اینترفیس IValueConverter ، از دلیگیت استفاده میکرد ، خیلی راحت تر بودیم . مجبور نبودیم برای هر شی از Binding ای که به تبدیل نیاز داره ، یه کلاس مجزا بسازیم .
یا حداقل 2 نوع converter میزد . یکی از اینترفیس و یکی هم از دلیگیت استفاده میکرد .

نمیشه ما یه کاری کنیم (یه کلاسی بسازیم و یا کار دیگه ای) که Converter را بجای اینکه یه کلاسی بهش بدیم ، یه دلیگیت ای بهش بدیم؟
تا برای هر شی از Binding (که نیاز به converter داریم) ، از اون متدها استفاده کنیم؟
آخه این جوری خیلی بدجور میشه . فرض کنید در یه پروژه که 100 تا Binding ای انجام میدیم که نیاز به Convert دارن . 100 تا هم براشون باید کلاس مجزا بسازیم .

پس برای چی دارید مشخصه می سازید؟

اگر قراره ImageSource ئه فقط داخل خود View استفاده بشه مشخصه اش برای چیه؟

دقیقا منظورتون را متوجه نشدم .
پروپرتیِ نوعِ BackupStatus که در Model لازم هست که اطلاعات وضعیت بکاپ سیستم کاربر را توی خودش داشته باشه .
پروپرتیِ نوعِ ImageSource در View را هم حداقل به عنوان Binding Source Property برای پروپرتیِ ImageSource ئه شیِ ImageDrawing (که در شیِ Image استفاده میشه) میخوام .

یا اینکه منظورتون اینه که بجای این همه کار ، یه پروپرتیِ نوعِ BackupStatus که در Model تعریف کردم ، حالا بجای اینکه پروپرتیِ نوعِ ImageSource را در View تعریف کنم ، مستقیما پروپرتیِ BackupStatus در Model را با یه Converter ، به عنوان Binding Source Property برای پروپرتیِ ImageSource ئه شیِ ImageDrawing (که در شیِ Image استفاده میشه) ، استفاده کنم؟
منظورتون اینه که میگین پس تعریفِ پروپرتیِ نوعِ ImageSource در View را میخوام چی کار؟


از بیرون بهش ImageSource میرسه؟

از بیرون (از Model) ، بهش Enum ای از نوع BackupStatus میرسه . البته به این پروپرتی نمیرسه .
نوع Enum ، به متدی در View میرسه که بعدش ، اون نوع را در متد ، تبدیل به ImageSource میکنم .
اون متد در View هم حالا یا به عنوان دلیگیت ، از رویدادی در ViewModel فراخونی میشه یا روشی شبیه به این .

اگر قراره مقدار ImageSource ئه وابسته به Enum باشه و ImageSource ئه توسط کدی در View ایجاد بشه و بعد در المنت های View نمایش داده بشه، چرا دیگه اصلا برای ImageSource ئه مشخصه تعریف می کنید؟

برای مقدار string یا object اون Enum ئه مشخصه بسازید. همون موقع که مقدار string یا object اون Enum رو در یک مشخصه View دریافت کردید ImageSource رو بسازید و بی واسطه در المنت مورد نظر قرار بدهید.

من اگه بگم دقیق متوجه نشدم ، میبخشید من را؟
این ، همین روشی نیست که من الان دارم میرم مگه؟

طبعا هم وقتی مقدار enum تغییر بکنه، رابط در ViewModel هم به واسطه INotifyPropertyChanged مطلع میشه و مقدار جدیدی منتقل می کنه، Binding ای که مقدارش رو به View منتقل می کنه به View اطلاع میده و نیازی به اتصال دستی متد به رخداد PropertyChanged نیست.

اون پروپرتی نوع string را در ViewModel شاید نسازم . احتمالا نوع BackupStatus را از Model میگیرم (توسط ViewModel به View منتقل میکنم) و در View هم که اطلاعاتِ BackupStatus را بصورت Object که در متدی گرفتم ، نوع رشته و کلا تبدیل به نوعِ ImageSource را مستقیما همونجا انجام میدم .

تشکر استاد .
 

the_king

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

نوع ImageSource که طبق چیزی که گفته بودین ، به View مربوط میشه (پروپرتی اش در View تعریف میشه) .
اطلاعات BackupStatus هم که در پروپرتی ای در Model تعریف میشه .
از Converter هم که برای بایندینگ فعلا نمیخوام استفاده کنم .
پس لازمه اطلاعات تغییرِ شیِ پروپرتیِ نوعِ BackupStatus ، از Model به ViewModel و بعد به View منتقل بشه دیگه؟
بله، همه اینها درسته، ایجاد ImageSource رو هم در View انجام می دهید، اما چرا برای ImageSource ئه دارید مشخصه میسازید؟
منظورتون پروپرتیِ نوعِ ImageSource هست؟
اگه آره ، برای اینکه این پروپرتی را به عنوان Binding Source Property برای پروپرتیِ ImageSource ئه شیِ ImageDrawing (که در شیِ Image استفاده میشه) ، استفاده کنم و بهش Binding کنم .
مساله همینه، مشخصه ImageSource ئه خودش خود به خود که مقدار نمیگیره، بهش مقدار می دهید و زمانی اینکار رو می کنید که مقدار enum ئه تغییر کنه. یعنی ImageSource صرفا حاصل تبدیل ئه از نوعی به نوع دیگری، یک مقدار مستقل از اون enum نیست. مثلا پنجره چرا مشخصه Width داره؟ چون قراره بتوانید مقدار Width رو از بیرون پنجره اش تعیین کنید، یک مقدار شیء رو خارج از روال داخلی کلاس اش تعیین کنید. اگر مقدار Width همیشه بر اساس عنوان پنجره تعیین میشد و وابسته به مقدار دیگری بود که دیگه مشخصه Width بدرد نمیخورد.
ImageSource که از بیرون کلاس مقدار نمی گیره، صرفا حاصل تبدیل مقدار enum به مسیر یک منبع تصویر ئه، تبدیلش هم داخل خود کلاس رخ میده. یعنی یک روال داخلی ئه.
مقدار ImageSource ئه بر اساس چی تعیین میشه؟ مقدار enum ئه، کی مقدار ImageSource ئه تغییر می کنه؟ فقط وقتی مقدار enum ئه تغییر کنه. ImageSource ئه مستقل مقدار نمیگه که نیاز به Bind کردن داشته باشه. وقتی مقدار enum ئه تغییر کرد View با خبر میشه و مقدار جدیدی به ImageSource در شیء فلان و بهمان میده. اگر مشخصه بخواهید برای دریافت مقدار enum بصورت object / string ئه، نه ImageSource ای که صرفا داخل خود کلاس قراره به یک شیء مقدار بده.
خودِ این پروپرتی (از نوعِ ImageSource که در View تعریف شده هست) ، با تغییرِ مقدارِ پروپرتیِ نوعِ BackupStatus (که در Model تعریف شد) ، تغییر میکنه . اما چون نوع این دو پروپرتی با هم متفاوت هستن (یکی از نوع BackupStatus و یکی هم از نوع ImageSource) ، و چون حداقل تا الان نمیخوام از Converter برای بایندینگ شون استفاده کنم ، پس نمیتونم این دو پروپرتی را با هم Binding کنم.
نیازی هم نیست که بهم Bind کنید.
در پرانتز اینو بگم که مایکروسافت برای استفاده از converter در Binding ، بجای استفاده از اینترفیس IValueConverter ، از دلیگیت استفاده میکرد ، خیلی راحت تر بودیم . مجبور نبودیم برای هر شی از Binding ای که به تبدیل نیاز داره ، یه کلاس مجزا بسازیم .
یا حداقل 2 نوع converter میزد . یکی از اینترفیس و یکی هم از دلیگیت استفاده میکرد .
نمیشه ما یه کاری کنیم (یه کلاسی بسازیم و یا کار دیگه ای) که Converter را بجای اینکه یه کلاسی بهش بدیم ، یه دلیگیت ای بهش بدیم؟
تا برای هر شی از Binding (که نیاز به converter داریم) ، از اون متدها استفاده کنیم؟
آخه این جوری خیلی بدجور میشه . فرض کنید در یه پروژه که 100 تا Binding ای انجام میدیم که نیاز به Convert دارن . 100 تا هم براشون باید کلاس مجزا بسازیم .
برنامه نویس شما هستید، شما هستید که تصمیم می گیرید در کد چه کار کنید، نه مایکروسافت. فرضا اگر شما یک کلاس IValueConverter بسازید که بر اساس مقدار یک مشخصه اش صد جور تبدیل انجام بده، مایکروسافت جلوتون رو میگیره؟ قطعا نه. دست شما همیشه در انتخاب روش باز ئه.
دقیقا منظورتون را متوجه نشدم .
پروپرتیِ نوعِ BackupStatus که در Model لازم هست که اطلاعات وضعیت بکاپ سیستم کاربر را توی خودش داشته باشه .
بله.
پروپرتیِ نوعِ ImageSource در View را هم حداقل به عنوان Binding Source Property برای پروپرتیِ ImageSource ئه شیِ ImageDrawing (که در شیِ Image استفاده میشه) میخوام .
ابهام من سر نیاز شما به این مشخصه است، چرا بهش نیاز دارید؟ فرض کنید بجای اون ImageSource یک مشخصه داشتید به نام BackupStatusObject از نوع object که مقدارش از اون BackupStatus ئه به واسطه ViewModel تامین میشه.
وقتی مقدار این مشخصه BackupStatusObject ئه set میشه (که نتیجه تغییر مقدار BackupStatus در Model است) شما نباید شیء ImageSource جدید رو بسازید و بعد داخل ImageDrawing قرار بدهید؟ که اینکار رو هم می توانید در set ئه انجام بدهید. Bind کردن میخواد؟ نه. دیگه مشخصه ImageSource و Bind کردنش برای چیه؟ شما زمانی به ImageSource و Bind داشتید که ImageSource یک مشخصه مستقل از enum بود که قرار بود استفاده کننده از کلاس بتونه بهش مقدار بده و با تغییر مقدارش فوری در ImageDrawing تاثیر رو منعکس کنید. اما شما دارید View ای میسازید که ImageDrawing اش بر اساس مقدار enum تغییر ظاهر میده، مشخصه ImageSource مستقلی ندارید که از بیرون کلاس مقدار بگیره.
یا اینکه منظورتون اینه که بجای این همه کار ، یه پروپرتیِ نوعِ BackupStatus که در Model تعریف کردم ، حالا بجای اینکه پروپرتیِ نوعِ ImageSource را در View تعریف کنم ، مستقیما پروپرتیِ BackupStatus در Model را با یه Converter ، به عنوان Binding Source Property برای پروپرتیِ ImageSource ئه شیِ ImageDrawing (که در شیِ Image استفاده میشه) ، استفاده کنم؟
نه، می توانید از Converter استفاده کنید ولی نیازی به Converter نیست و منم نگفتم از Converter استفاده کنید. سوال من اینه، چرا برای ImageSource ای که از بیرون کلاس مقدار نمیگیره مشخصه تعریف می کنید، چرا چیزی رو Bind می کنید که مقدار خودش باید از طریق یک enum تامین بشه که تبدیل مقدارش رو داخل خود کلاس انجام می دهید. اینجا Bind نمیخواد، مشخصه ImageSource نمیخواد. شما نهایتش یک مشخصه برای BackupStatusObject میخواهید که اگه اونم نسازید اتفاقی نمی افته، شما فقط باید به طریقی View رو از مقدار enum و تغییر مقدارش با خبر کنید، حالا چه با یک مشخصه و چه هر طریق دیگری.
منظورتون اینه که میگین پس تعریفِ پروپرتیِ نوعِ ImageSource در View را میخوام چی کار؟
بله.
از بیرون (از Model) ، بهش Enum ای از نوع BackupStatus میرسه . البته به این پروپرتی نمیرسه .
همین، نمیرسه. شما به ImageSource مقداری از بیرون نمی دهید، دارید داخل خود کلاس به مشخصه ای مقدار می دهید که بود و نبودش تاثیری نداره و صرفا استفاده داخلی داره.
نوع Enum ، به متدی در View میرسه که بعدش ، اون نوع را در متد ، تبدیل به ImageSource میکنم .
اون متد در View هم حالا یا به عنوان دلیگیت ، از رویدادی در ViewModel فراخونی میشه یا روشی شبیه به این .
بله. اینها رو میدونم.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بله، همه اینها درسته، ایجاد ImageSource رو هم در View انجام می دهید، اما چرا برای ImageSource ئه دارید مشخصه میسازید؟

مساله همینه، مشخصه ImageSource ئه خودش خود به خود که مقدار نمیگیره، بهش مقدار می دهید و زمانی اینکار رو می کنید که مقدار enum ئه تغییر کنه. یعنی ImageSource صرفا حاصل تبدیل ئه از نوعی به نوع دیگری، یک مقدار مستقل از اون enum نیست. مثلا پنجره چرا مشخصه Width داره؟ چون قراره بتوانید مقدار Width رو از بیرون پنجره اش تعیین کنید، یک مقدار شیء رو خارج از روال داخلی کلاس اش تعیین کنید. اگر مقدار Width همیشه بر اساس عنوان پنجره تعیین میشد و وابسته به مقدار دیگری بود که دیگه مشخصه Width بدرد نمیخورد.
ImageSource که از بیرون کلاس مقدار نمی گیره، صرفا حاصل تبدیل مقدار enum به مسیر یک منبع تصویر ئه، تبدیلش هم داخل خود کلاس رخ میده. یعنی یک روال داخلی ئه.

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

البته پروپرتیِ نوعِ ImageSource در View ، بصورت private تعریف میشه .
public تعریف نمیشه که هم بشه بیرون از کلاس هم مقداردهی کرد .


سوال من اینه، چرا برای ImageSource ای که از بیرون کلاس مقدار نمیگیره مشخصه تعریف می کنید، چرا چیزی رو Bind می کنید که مقدار خودش باید از طریق یک enum تامین بشه که تبدیل مقدارش رو داخل خود کلاس انجام می دهید. اینجا Bind نمیخواد، مشخصه ImageSource نمیخواد. شما نهایتش یک مشخصه برای BackupStatusObject میخواهید که اگه اونم نسازید اتفاقی نمی افته، شما فقط باید به طریقی View رو از مقدار enum و تغییر مقدارش با خبر کنید، حالا چه با یک مشخصه و چه هر طریق دیگری.

البته این هم نکته ای هست .
ولی استفاده از پروپرتی و Binding کردنش هم چندان ، اشکالی نداره و قانون یا چیزی را نقض نمیکنه دیگه .

نیازی هم نیست که بهم Bind کنید.

برنامه نویس شما هستید، شما هستید که تصمیم می گیرید در کد چه کار کنید، نه مایکروسافت. فرضا اگر شما یک کلاس IValueConverter بسازید که بر اساس مقدار یک مشخصه اش صد جور تبدیل انجام بده، مایکروسافت جلوتون رو میگیره؟ قطعا نه. دست شما همیشه در انتخاب روش باز ئه.
نه، می توانید از Converter استفاده کنید ولی نیازی به Converter نیست و منم نگفتم از Converter استفاده کنید.

استاد
میگم استفاده از Converter در بایندینگ ، هم بد نیست ها .
البته Converter ای که یه شی از فقط یک کلاس باشه اما در متد Convert اش بشه انواع بایندینگ ها را بصورت انحصاری تشخیص داد تا برای هر شی از بایندینگ ، متدِ مربوط به کارِ خودش را انجام داد . تا برای همه اشیاء از بایندینگ که در پروژه استفاده میکنیم ، فقط از یک کلاس استفاده کنیم و کلاس های متفاوت نسازیم .


آیا میشه در متد Convert ، شیِ Binding ئه مربوطه را براش ارسال کرد و اون شیِ بایندینگ را در متدِ Convert دریافت کرد تا از این طریق ، متوجه بشیم که این شیِ بایندینگ ، همون شیِ بایندینگ ای که به پروپرتیِ خاصی نسبت داده بودیم هست تا در این صورت ، متد و روالِ مربوط به تبدیل برای اون را انجام بدم؟
متوجه ی منظورم شدید؟

فرضا این روش چطوره (و آیا شدنی هست) که در parameter ئه بایندینگ (ای که برای convert میتونیم تعیین کنیم) ، همون شیِ Binding را به عنوان پارامتر ارسال کنیم؟


یا هر روش دیگه ای که در متد convert ، بشه انحصارِ بایندینگ را تشخیص داد .
فرضا روی مقدار Binding Source Property که در پارامتر اولِ متدِ Convert ، میشه بدست آورد ، چون همون Binding Source Property را میشه در چندین شی از Binding استفاده کرد ،انگار نمیشه ازش انحصار و شناسه ی بایندینگ مورد نظر را بدست آورد .
یا فرضا از Binding Target Property Type که در پارامتر دوم این متد هست ،چون ممکنه بعدا شیِ Binding برای پروپرتیِ Target را هم تغییر داد ، باز هم نمیشه یا سخته که از این پارامتر بخوایم شناسه ی بایندینگ مورد نظرمون را بدستبیاریم .

پس با چه روشی میشه شناسه ی Binding را در متد Convert ، بدست بیاریم؟
تشکر استاد . :rose:
 

the_king

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

SajjadKhati

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

سلامی مجدد استاد .
خیلی ممنون :rose:
بله . من هم شرمنده ام . :rose:
برای اینکه وقت تون کمتر گرفته شه ، جواب ها را خلاصه تر هم بگین برام ممکنه کافی باشه . (مثلا جواب ها اگه نصف هم باشن ، ممکنه کافی باشه) .

البته من هنوز این قضیه را پیاده سازی نکردم (که استفاده از پروپرتی را برای ImageSource پیاده سازی کرده باشم یا نه) . فعلا میخوام روش استفاده را برم .
الان توی روش Converter برای Binding ، اگه بتونم شناسه ای را در متد Convert دریافت کنم ، روش Converter انگار خیلی به صرفه تر میشه .
آیا میشه توی متد Convert ، شناسه ای از اون شیِ Binding یا خود شیِ Binding را بدست آورد؟

----------

استاد اگه ناراحت نمیشین ، یه نقد کوچیک کنم . قبل تر ، یه کم صبرتون بیشتر از حالا بود . :green:
مثلا چند باری بود که قبلا روش خودم را رفته بودم ، باز نهایتا برگشتم به حرف شما . هر چند ضرر کرده بودم اما اون باعث شد تجربه ی شخصی ام بیشتر بشه . که اونها کسب تجربه ای برام شد .
نمونه ی خیلی بزرگش ، ساخت کنترل Transparent Control در Windows Form بود که شما از اول با ساخت و طراحی اش مخالف بودین اما من حداقل چون نیاز بهش داشتم ، شروع به ساختش کردم .
هر چند کنترل بدی در حد خودش نشد اما باز خیلی مشکلات داشت که شما از اول بهش اشاره میکردید اما من چون نیاز داشتم و بر اساس بی تجربگی ام ، ساختمش . ساخت اون کنترل ، هر چند تجربه ی خوبی شد برام اما چند ماه زمان برد و خوب درک کردم که چرا و چجوری هه که Windows Form از اساس با کنترل های Transparent مشکل داره و نهایتا به حرف شما رسیدم که اگه نمیساختمش ، بهتر بود . یعنی ضررش از منافعش بیشتر بود .


یا قضیه ی همین برنامه ی بکاپ vss که شما از اول چندان باهاش موافق نبودید . احتمال داره موفق هم نشه ولی حداقل برای کسب تجربه ، بد نیست .
هدف حرفم اینه که مثل قبل ، صبوری به خرج بدین و هر چند با راهنمایی های بسیار مفید تون اما انتخاب آخر را به دست خودمون بسپارین (هر چند انتخاب بدی هم کرده باشیم) ، حداقل تجربه مون بیشتر میشه و در عمل متوجه میشیم چرا روشی که تاکید میکردین ، فایده اش بیشتر هست .

هر چند ، تا حالا اغلب قریب به اتفاق راهنمایی هایی که کردین را در نظر گرفتم و پیاده کردم .

تشکر
 
آخرین ویرایش:

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

بالا