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

the_king

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

XAML Syntax In Detail - WPF

اگه توی کلاسی ، از پروپرتیِ یک کلاسِ دیگه استفاده کنیم ، پردازنده ی xaml در wpf ، اون پروپرتی را به عنوان attached property میشناسه . درسته؟
نه. نمیگه میشناسه، میگه رفتار پردازشگر در این شرایط مثل رفتار با یک مشخصه الحاقی است، یعنی در چنین حالتی پردازشگر انتظار داره که با یک مشخصه الحاقی طرف باشه، گزینه دیگری نمونده.
پردازشگر نه در کلاس خود Button همچین مشخصه Label.Background ای رو دیده و نه در سلسله وراثت Button، پس تنها گزینه ای که برای پردازش باقی مونده مشخصه الحاقی است که اگر Label.Background مشخصه الحاقی هم نباشه (که نیست) گزینه دیگری برای پردازشگر نمونده و متن ئه قابل پردازش نیست.

Attached Property کد نویسی متفاوتی داره و مشخصه عادی نمیتونه بصورت مشخصه الحاقی عمل کنه. مشخصه الحاقی صریحا در کد کلاس به عنوان مشخصه الحاقی ثبت میشه، مشخصه معمولی اینطوری ثبت نشده.
در مشخصه عادی یک فیلد DependencyProperty ئه static رو در یک مشخصه public که در کلاس اش تعریف شده بکار می برند، مثلا BackgroundProperty رو در مشخصه Background بکار می برند.
اما در مشخصه الحاقی یک فیلد DependencyProperty ئه static رو با DependencyProperty.RegisterAttached ثبت می کنند، مثلا ColumnProperty رو ثبت می کنند. دیگه مشخصه ای مثل Column در Grid تعریف نشده که از ColumnProperty استفاده کنه.

مثلا در تگ Button ای ، به عنوان attributes اش ، از Label.Background استفاده کنیم ، در این صورت ، پردازنده ی xaml در wpf ، این روپرتی را سعی میکنه به عنوان attached property پردازش کنه اما چون این پروپرتیِ Label.Background در راهنمای سایت اش (و کلا) به عنوان attached property مشخص نشد ، پس ارور میده . درسته؟
بله. البته پردازشگر بر اساس بود و نبود اون کد RegisterAttached با اسمی مثل "Background" برای نوع typeof(Label) میتونه بفهمه که مشخصه الحاقی با این نام هست یا نه. کد کلاس ای مثل Grid رو ببینید.
کد:
[CommonDependencyProperty]
    public static readonly DependencyProperty ColumnProperty = DependencyProperty.RegisterAttached("Column", typeof(int), typeof(Grid), new FrameworkPropertyMetadata(0, new PropertyChangedCallback(Grid.OnCellAttachedPropertyChanged)), new ValidateValueCallback(Grid.IsIntValueNotNegative));

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

SajjadKhati

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

the_king

مدیرکل انجمن
خیلی ممنون استاد .
استاد ، یه کنترلی توی wpf هست که عملکردی شبیه transparent control ای که نوشته بودم را داشته باشه؟
یعنی یه شکل را به عنوان ورودی بهش بدیم و از همون شکل ، بتونیم شکل های دیگه با رنگ های متفاوت دیگه ای را به عنوان رویدادهای دیگه ی اون کنترل در زمان طراحی ، در نظر بگیریم؟
متوجه ی منظورم هستین یا اینکه بیشتر توضیح بدم؟ (چون در جریان ساخت اون کنترل بودین ، عرض میکنم)
یا اگه کنترلی نیست ، کلا نزدیک ترین روشی که این عملکرد (رنگ های متفاوت دادن به یک bitmap و ذخیره در bitmap جدید در زمان طراحی) را ارائه بده ، به نظرتون چه روشی هست و چجوری این قابلیت را در wpf پیاده سازی کنم؟
یا کلا بجای این کار ، پیشنهادتون اینه که مثلا همه ی bitmap ها (حتی بیت مپ هایی که صرفا رنگ شون هم متفاوت هست) را جداگانه در فتوشاپ طراحی و ذخیره کنم؟ (این روش را زیاد نمیپسندم) .
یا روش های دیگه ای به ذهن تون میرسه؟
(نمیخوام برای این کار دوباره یه کلاس کنترل جدید در wpf بسازم . هر چند خیلی کمتر ولی باز زمان بر هست) .
خیلی ممنون .
از اساس WPF برای طراحی مبتنی بر بردار مناسب ئه، نه تصاویر bitmap. می خواهید کاری رو انجام بدهید که برای اجرا در WPF ایده خوبی نیست.
بجای اینکه تصویر Bitmap رو دستکاری کنید می توانید روی انیمیشن، اضافه کردن لایه نیمه شفاف، اشکال برداری و ... کار کنید. هر چیزی که با بزرگنمایی کیفیتش کاهش پیدا نکنه.
اگه یک مدتی صرف بررسی نمونه کد های WPF کنید، دید بهتری نسبت به پلتفرم و قابلیت هاش پیدا می کنید.
 

SajjadKhati

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

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

همونطور که میدونید ، من یک تصویر را در فتوشاپ طراحی کردم (یه سری هم که طراحی شو شما زحمت کشیده بودین) که پشت زمینه ی transparent داره و رنگِ اون شکل هم یکدست سفید با فرمت png هست . مثلا شکل دکمه ی تنظیمات با رنگ سفید طراحی شد . این شکل ، بصورت استاندارد (به عنوان کنترل Button یا کنترل Image) در wpf نشون داده میشه اما میخوام وقتی کاربر موس را روی این کنترل برد ، رنگ BitmapImage (یا هر شی دیگه ای در wpf که بشه این شکل ای که در فتوشاپ طراحی شده را بهش داد) که سفید بود را به یه رنگ دیگه (مثلا آبی) ، تغییر رنگ بده .

خوب ، پروپرتی ای برای تغییر رنگ برای این کار وجود نداره که بخوام اون پروپرتی را انیمیشن کنم .
درباره ی قضیه ی لایه ی نیمه شفاف یا اشکال برداری و اینکه چجوری با اینها ، این قضیه را انجام بدم ، نمیدونم چجوری هه . یه کم بیشتر در این باره توضیح میدین؟ اگه یه مثال کوچیک هم بزنین که چجور میشه این قضیه را انجام داد ، خیلی ممنون میشم (فقط رنگ یک BitmapImage یا هر شی دیگه ای که بجاش کاربرد داشته باشه را بشه تغییر داد) .
یا به نظرتون چطوره بجای xml ، از کد سی شارپ استفاده کنم تا فقط زمان اجرای برنامه ، در اون رویدادها ، تغییرات رنگ داشته باشه؟
 

SajjadKhati

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

من مثالی که توی سایتش بود ، یعنی مثال زیر را بررسی کردم :

کد:
Stream imageStream = new FileStream("tulipfarm.jpg", FileMode.Open, FileAccess.Read, FileShare.Read);
BitmapSource myBitmapSource = BitmapFrame.Create(imageStream);
BitmapFrame myBitmapSourceFrame = (BitmapFrame)myBitmapSource;
ColorContext sourceColorContext = myBitmapSourceFrame.ColorContexts[0];
ColorContext destColorContext = new ColorContext(PixelFormats.Bgra32);
ColorConvertedBitmap ccb = new ColorConvertedBitmap(myBitmapSource, sourceColorContext, destColorContext, PixelFormats.Pbgra32);
Image myImage3 = new Image();
myImage3.Source = ccb;
myImage3.Stretch = Stretch.None;
imageStream.Close();

اما در خطی که نوشته :
ColorContext sourceColorContext = myBitmapSourceFrame.ColorContexts[0];
ارور میده چون مقدار ColorContexts[0] ، نال هست . مشکل مهم اش اینه که شی myBitmapSource را به کلاس BitmapFrame تبدیل کردن که از نوع کلاس abstract هست . مایکروسافت که انگار در ادامه ، دیگه سلسله مراتب ارث بری را برای این کلاس در نظر نگرفت و این کلاس توسط مایکروسافت ، فرزندی براش ساخته نشد اما با این حال نمیدونم در کد بالا چرا ازش استفاده کردن .
ColorContext هم نمیدونم دقیقا چیه و آیا کلاسی هست که مثلا میشه توش رنگ خاصی تعریف کرد و اون رنگ را برای ColorConvertedBitmap در نظر گرفت تا توی شی BitmapSource مون ست کنه یا نه؟

همچنین نظرتون راجع به استفاده از کلاس WriteableBitmap بجای کلاس ColorConvertedBitmap چیه؟
 

the_king

مدیرکل انجمن
خیلی ممنون استاد .
بزرگنمایی نمیخوام انجام بدم .
شما انجام نمی دهید، WPF باید برای کنترل ای که قراره در ابعاد بزرگتر نمایش داده بشه رو بزرگ کنه، تصویر هم که بزرگ بشه کیفیتش پایین میاد. اگر تغییر ابعاد و حفظ کیفیت مهم نیست بجای محیط برداری WPF از Windows Forms استفاده می کنیم که بر مبنای طراحی پیکسلی است. طراح Button که نمیگه نمیخوام بزرگنمایی انجام بدم و ابعاد Button باید همیشه فلان باشه. WPF مزیت اش در همینه که بتونه با حفظ کیفیت در ابعاد متفاوتی نمایش داده بشه، اگر بزرگنمایی برای کنترل ای مشکل ایجاد کنه برای WPF مناسب نیست.

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

همونطور که میدونید ، من یک تصویر را در فتوشاپ طراحی کردم (یه سری هم که طراحی شو شما زحمت کشیده بودین) که پشت زمینه ی transparent داره و رنگِ اون شکل هم یکدست سفید با فرمت png هست . مثلا شکل دکمه ی تنظیمات با رنگ سفید طراحی شد . این شکل ، بصورت استاندارد (به عنوان کنترل Button یا کنترل Image) در wpf نشون داده میشه اما میخوام وقتی کاربر موس را روی این کنترل برد ، رنگ BitmapImage (یا هر شی دیگه ای در wpf که بشه این شکل ای که در فتوشاپ طراحی شده را بهش داد) که سفید بود را به یه رنگ دیگه (مثلا آبی) ، تغییر رنگ بده .
اگر تصویر یک ناحیه است که باید از یک رنگ به یک رنگ دیگه تغییر کنه، به این معنا است که صرفا جزئیات محیطی است که باید با رنگ جدیدی یکدست پر بشه، یعنی یک Path ئه، یک Shape ئه، Brush اش رو تغییر می دهید و رنگش عوض میشه و اگر از ابتدا بجای ناحیه برداری از تصویر bitmap برای اینکار استفاده شده انتخاب bitmap برای اینکار اشتباه بوده.
اگر تصویر یک شکل رنگ و وارنگ و با جزئیات ئه، که باید مقداری روشن تر یا تیره تر یا به رنگی متمایل بشه، یک لایه نیمه شفاف روی اون که رنگ خاصی داره میتونه روی اون تصویر قرار بگیره و این ظاهر رو ایجاد کنه.
اما اگر موضوع چیز دیگری است، دنبال چیزی که بگردید که مناسب اش باشه، دوچرخه رو انتخاب نکنید که بعدا قرار باشه پرواز کنه. WPF برای پردازش تصاویر Bitmap مناسب نیست.
 

SajjadKhati

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

خیلی ممنون استاد .
خوب ، wpf همینجوری نمیاد کنترل را در ابعاد بزرگتر رسم کنه .
باید برنامه نویس اون کنترل را تغییر اندازه بده (یا توسط کاربر ، باید پروژه تغییر اندازه پیدا کنه که باعث بشه اون کنترل تغییر اندازه پیدا کنه که تغییرِ اندازه ی کنترل را هم برنامه نویس در این شرایط میتونه نظارت کنه و نذاره اون کنترل تغییر اندازه بده)

اگر تغییر ابعاد و حفظ کیفیت مهم نیست بجای محیط برداری WPF از Windows Forms استفاده می کنیم که بر مبنای طراحی پیکسلی است. طراح Button که نمیگه نمیخوام بزرگنمایی انجام بدم و ابعاد Button باید همیشه فلان باشه. WPF مزیت اش در همینه که بتونه با حفظ کیفیت در ابعاد متفاوتی نمایش داده بشه، اگر بزرگنمایی برای کنترل ای مشکل ایجاد کنه برای WPF مناسب نیست.

بله . برای این نوع کنترل هام ، مهم نیست چون قرار نیست ابعادش را بزرگتر کنم .
wpf را فقط برای این نوع کنترل هام استفاده نمیکنم . این نوع کنترل ها ، بخشی از کنترل های درون پروژه ام را شامل میشن . بخش های دیگه ، کنترل های دیگه مثل tabcontrol و چک باکس و ... هستند که نیاز به ساخت template براشون دارم .
همچنین علاوه بر قضیه ی template ، کلا سیستم گرافیکی wpf خیلی خیلی بهتر هه مثل انیمیشن کردن و ... .

به ظاهر شما با تغییر تصویر دکمه می خواهید جلوه اش بر اساس رخداد ها تغییر کنه، اگر هدف تون تغییر ظاهر ئه، هر راهی که به تغییر ظاهر منجر بشه به این قضیه مربوط ئه.
ظاهر دکمه شما بر اساس رخداد ها تغییر میکنه، مثلا وقتی ماوس روی اون قرار میگیره یا دکمه ماوس فشرده میشه. انیمیشن و تغییر رنگ و مشخصات اشکال برداری و لایه های شفاف بالای و پایین هم ظاهر رو تغییر می دهند.


اگر تصویر یک ناحیه است که باید از یک رنگ به یک رنگ دیگه تغییر کنه، به این معنا است که صرفا جزئیات محیطی است که باید با رنگ جدیدی یکدست پر بشه، یعنی یک Path ئه، یک Shape ئه، Brush اش رو تغییر می دهید و رنگش عوض میشه و اگر از ابتدا بجای ناحیه برداری از تصویر bitmap برای اینکار استفاده شده انتخاب bitmap برای اینکار اشتباه بوده.
اگر تصویر یک شکل رنگ و وارنگ و با جزئیات ئه، که باید مقداری روشن تر یا تیره تر یا به رنگی متمایل بشه، یک لایه نیمه شفاف روی اون که رنگ خاصی داره میتونه روی اون تصویر قرار بگیره و این ظاهر رو ایجاد کنه.
اما اگر موضوع چیز دیگری است، دنبال چیزی که بگردید که مناسب اش باشه، دوچرخه رو انتخاب نکنید که بعدا قرار باشه پرواز کنه. WPF برای پردازش تصاویر Bitmap مناسب نیست.

حالا استاد ، تغییر اندازه ی کنترل صورت نمیگیره و بنابراین کیفیت برام مهم نیست اما با این حال اگه چیزی که شما میگید ، بشه که باز بهتر میشه .
این حالتی هم که شما میگید ، انگار فقط در یک صورت امکان پذیر هه اون هم اگه بشه یک ImageSource را به Shape یا Geometry تبدیل کرد . تبدیلش امکان پذیره؟ (حالا نمیدونم توسط blender یا با کدنویسی قابل انجام هست یا نه) .
چون شکل اولیه را باید توی فتوشاپ طراحی بشه . مثلا شکل زیر که تصویر "آیکون تنظیمات" هست (فایل png) را میشه به Shape یا Geometry تبدیل کرد؟ :

Setting.png

یعنی من فقط اون بخش هایی از تصویر بالا که رنگ آبی داره را لازم دارم (که به عنوان Shape یا Geometry تبدیل بشه) .
 

SajjadKhati

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

WriteableBitmap Class (System.Windows.Media.Imaging)

در اون مثالی که زد ، خط :

کد:
                    int color_data = 255 << 16; // R
                    color_data |= 128 << 8;   // G
                    color_data |= 255 << 0;   // B

اش را توضیح میدین؟
البته از عملگرهای شبفت و اور ای که استفاده کرد مطلع ام ولی دقیق درک نمیکنم که اولا مثلا چرا در خط اول ، عدد 255 را 16 بیت به سمت راست منتقل کرد؟ مثلا چرا 4 بیت نکرد؟ (یعنی این عدد 15 را از کجا آورد)؟ و همچنین خط دوم را چرا 8 بیت جابجا کرد؟ آیا بخاطر اینکه 16 میلیون و خردی رنگ داریم ، این عدد 16 در خط اول از این قضیه آب میخوره؟ اگه آره حالا از کجا سریع فهمید که عدد 255 را 16 بیت جابجا کنه ، به عدد 16 میلیون و خردی میرسه؟ (البته میتونم خودم حساب کنم و دونه دونه برم جلو و این قضیه را چک کنم اما سریع نمیتونم متوجه بشم که عدد 255 را باید 16 بیت به سمت راست منتقل کنیم تا به عدد 16 میلیون و خردی برسیم) .
و دوم اینکه از کجا فهمید که چه مقداری باید جابجا کنه؟
از کجا فهمید در خط دوم و سوم باید از عملگر اور هم استفاده کنه؟
و کلا هدفش از این کار چیه؟


و همچنین اگه از کد زیر استفاده نکنیم ، اشکالی داره؟

کد:
writeableBitmap.AddDirtyRect(new Int32Rect(column, row, 1, 1));

چون انگار این متد فقط منطقه ای که قبلا تغییر دادیم (رنگ پیکسل های اون منطقه را تغییر دادیم) را مشخص میکنه . که انگار نباید فایده ی خاصی داشته باشه چون خوب محتوای پیکسل ها (رنگ اش) را تغییر دادیم دیگه . فایده داره؟
 

the_king

مدیرکل انجمن
خیلی ممنون استاد .
خوب ، wpf همینجوری نمیاد کنترل را در ابعاد بزرگتر رسم کنه .
باید برنامه نویس اون کنترل را تغییر اندازه بده (یا توسط کاربر ، باید پروژه تغییر اندازه پیدا کنه که باعث بشه اون کنترل تغییر اندازه پیدا کنه که تغییرِ اندازه ی کنترل را هم برنامه نویس در این شرایط میتونه نظارت کنه و نذاره اون کنترل تغییر اندازه بده)
خیر. Developing a Per-Monitor DPI-Aware WPF Application - Win32 apps

بله . برای این نوع کنترل هام ، مهم نیست چون قرار نیست ابعادش را بزرگتر کنم .
مثل اینه که بگید چتر مهم نیست چون قرار نیست بارون ببارم. مقیاس پذیری جزئی از خصوصیات WPF ئه.

حالا استاد ، تغییر اندازه ی کنترل صورت نمیگیره و بنابراین کیفیت برام مهم نیست اما با این حال اگه چیزی که شما میگید ، بشه که باز بهتر میشه .
این حالتی هم که شما میگید ، انگار فقط در یک صورت امکان پذیر هه اون هم اگه بشه یک ImageSource را به Shape یا Geometry تبدیل کرد . تبدیلش امکان پذیره؟ (حالا نمیدونم توسط blender یا با کدنویسی قابل انجام هست یا نه) .
چون شکل اولیه را باید توی فتوشاپ طراحی بشه . مثلا شکل زیر که تصویر "آیکون تنظیمات" هست (فایل png) را میشه به Shape یا Geometry تبدیل کرد؟ :

مشاهده پیوست 113464

یعنی من فقط اون بخش هایی از تصویر بالا که رنگ آبی داره را لازم دارم (که به عنوان Shape یا Geometry تبدیل بشه) .
نرم افزار ها و پلاگین های زیادی هستند که از روی تصویر بردار ایجاد می کنند و یا از SVG و سایر فرمت های برداری خروجی XAML تولید می کنند. البته هر چقدر ابعاد و کیفیت تصویر بالاتر باشه بردار دقیقتری درمیاد.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
خیر. Developing a Per-Monitor DPI-Aware WPF Application - Win32 apps


مثل اینه که بگید چتر مهم نیست چون قرار نیست بارون ببارم. مقیاس پذیری جزئی از خصوصیات WPF ئه.


نرم افزار ها و پلاگین های زیادی هستند که از روی تصویر بردار ایجاد می کنند و یا از SVG و سایر فرمت های برداری خروجی XAML تولید می کنند. البته هر چقدر ابعاد و کیفیت تصویر بالاتر باشه بردار دقیقتری درمیاد.

خیلی ممنون استاد .
منظورتون از نرم افزارها ، نرم افزاری جدای از ویژال استودیو یا blender هست؟
اگه آره ، خروجی شون xaml هست (که کدهاش در wpf شناخته شده باشه) ؟
کلا این نرم افزار یا پلاگین هایی که میگید را نام میبرید و معرفی میکنید؟
حتما باید فایل svg باشه؟ چون فایل ام png (در همون ابعادی که در پست 187 دادم) هست . باید فایل png را اول به svg تبدیل کنم؟
کلا یه کم در این باره توضیح بیشتری میدین؟
 

the_king

مدیرکل انجمن
خیلی ممنون استاد .
منظورتون از نرم افزارها ، نرم افزاری جدای از ویژال استودیو یا blender هست؟
اگه آره ، خروجی شون xaml هست (که کدهاش در wpf شناخته شده باشه) ؟
کلا این نرم افزار یا پلاگین هایی که میگید را نام میبرید و معرفی میکنید؟
حتما باید فایل svg باشه؟ چون فایل ام png (در همون ابعادی که در پست 187 دادم) هست . باید فایل png را اول به svg تبدیل کنم؟
کلا یه کم در این باره توضیح بیشتری میدین؟
SVG یکی از فرمت های برداری معروف بیشتر برای استفاده در وب و اینترنت ئه و اغلب نرم افزار های طراحی برداری هم خروجی SVG رو پشتیبانی می کنند.
اغلب سایت های جستجو آیکون هم svg جزو فرمت های متعارف شون ئه، مخصوصا برای سبک های طراحی Metro و Flat که آیکون ها ساده و تخت و تکرنگ در ابعاد مختلف نمایش داده میشن از آیکون های برداری استفاده میشه.
برای همین جستجوی آیکون مشابه ممکنه راه ساده تری باشه تا تبدیل اش، مخصوصا اگر طراحی برداری با تجربه ای نباشید.
تبدیل تصویر bitmap به بردار هم که قابلیت اغلب نرم افزار های طراحی برداری است. نرم افزار های طراحی برداری هم که خیلی متعدد هستند، CorelDraw و Illustrator و Inkscape و Freehand و ...
تو گوگل convert svg to xaml رو جستجو کنید تا انواع نرم افزار ها و پلاگین ها رو پیدا کنید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
به سمت پایین نیست، به سمت بالا است، Bubble ئه. کلیک در دکمه رخ داده و به سمت بالا (ریشه) حرکت کرده تا رسیده به TabControl و به مقصودش رسیده.


به سمت بالا یا Bubble به این مفهومه که در اون دکمه Button که در اولین سطر نوشته اید کلیک رخ بده و بعد بره به سمت Window تا ببینه برای این کلیک باید چه چیزی رو اجرا کنه. این میشه به سمت بالا. دیگه اگه به سمت بالا باشه اون ButtonBase.Click رو نمی بینه چون اون ButtonBase.Click در مسیر به سمت بالا دیده نمیشه.
رخداد های مسیریابی شده سه نوع متفاوت هستند، رخدادی مثل Click استراتژی Bubble داره، رخدادی مثل PreviewDrop استراتژی Tunnel داره و رخدادی مثل ToolTipOpening استراتژی Direct داره. طبعا توقع نداریم که رخدادی که استراتژی Bubble داره در فرزندش دنبال کاری که باید بکنه بگرده.
RoutingStrategy Enum (System.Windows)


شما یک Content دادید که میگید سمت چپ و بالا قرار بگیره و بچسبه به گوشه کادر، اما به گوشه کدوم کادر بچسبه؟ به گوشه کادر ContentPresenter ئه، نه خود Button. اون Button ئه Template داره و در Template اش گفته ContentPresenter ئه وسط قرار بگیره. شما هر چقدر هم که Content ئه رو به گوشه نزدیک کنید خود ContentPresenter که Content داخلش قرار داره وسط Button قرار میگیره و از گوشه Button فاصله داره.
باید Template ای بسازید که ContentPresenter وسط نباشه.


بس برای چه منظوری؟ برای برنامه نویسی؟ فکر نکنم فقط با دانستن کلیات بشه همچین کاری کرد.

خیلی ممنون استاد :rose:
دوباره برگشتیم به مبحث Routed Event :green:

میگم استاد ، الان استراتژی حباب ، اینه که از هر المنت ای که رویداد routed event را تعریف کردیم ، از همون المنت به سمت بالا حرکت میکنه تا به المنت ریشه (root element) که معمولا همون windows هست ، برسه . درسته؟
به عبارت دیگه ، از المنت ای که اون رویداد تعریف شد ، به سمت بالا حرکت میکنه و در مسیر (اش به سمت بالا) ، هر المنت (کنترل) ای را که با اون رویداد سازگار هست را اگه دید ، اون رویداد را به اون المنت متصل و اضافه میکنه . درسته؟

پس در کدی که مایکروسافت داده بود ، یعنی در کد زیر :

کد:
<Border Height="50" Width="300" BorderBrush="Gray" BorderThickness="1">
  <StackPanel Background="LightGray" Orientation="Horizontal" Button.Click="CommonClickHandler">
    <Button Name="YesButton" Width="Auto" >Yes</Button>
    <Button Name="NoButton" Width="Auto" >No</Button>
    <Button Name="CancelButton" Width="Auto" >Cancel</Button>
  </StackPanel>
</Border>

چرا رویداد Button.Click="CommonClickHandler" ، که در المنت StackPanel تعریف شد ، به سمت پایین اول حرکت کرد (یعنی اول ، به سمت المنت Button که فرزند StackPanel هست ، رفت) و بعد ، از اونجا به سمت بالا (به سمت ریشه که معمولا Window هست) حرکت میکنه؟
استراتژی حباب که نباید کاری به سمت پایین داشته باشه .
انتظار من از تعریف حباب این بود که وقتی در مثال بالا رویداد Button.Click در StackPanel تعریف شد ، به سمت بالا (در مثال بالا یعنی Border و احتمالا Grid و Window که در مثال بالا نوشته نشد) حرکت کنه و اگه در این مسیرش ، به المنت ای که سازگار با رویداد ButtonBase.Click بود ، برخورد کرد (که در مثال بالا ، در این مسیر ، همچین المنت ای که سازگار باشه وجود نداره) ، در اون صورت رویداد مربوط به اون المنت را به اون هندلر متصل و اضافه کنه .

یا در مثالی که در همین پست نقل قول کردم (یعنی مثال در پست شماره ی 162) .
من انتظار دارم که وقتی رویداد ButtonBase.Click در المنت TabControl در این مثال تعریف شد ، به سمت بالا حرکت کنه (یعنی به سمت Button ای که المنت TabControl به عنوانِ content ئه اون Button تعریف شد ، حرکت کنه) و رویداد Click از این دکمه (دکمه ای که والد TabControl هست) را به هندلر این متصل و رویداد اضافه کنه . اما برعکس اش شد . همه ی دکمه هایی که فرزندِ TabControl بودن را به این رویداد متصل کرد (یعنی به سمت پایین حرکت کرد) اما دکمه ی والد ئه TabControl که نسبت به TabControl ، در سمت بالا قرار داشت را کاری باهاش نداشت!

قضیه اش چجوری هه؟ من گیج شدم .
 

the_king

مدیرکل انجمن
خیلی ممنون استاد :rose:
دوباره برگشتیم به مبحث Routed Event :green:

میگم استاد ، الان استراتژی حباب ، اینه که از هر المنت ای که رویداد routed event را تعریف کردیم ، از همون المنت به سمت بالا حرکت میکنه تا به المنت ریشه (root element) که معمولا همون windows هست ، برسه . درسته؟
بله.
به عبارت دیگه ، از المنت ای که اون رویداد تعریف شد ، به سمت بالا حرکت میکنه و در مسیر (اش به سمت بالا) ، هر المنت (کنترل) ای را که با اون رویداد سازگار هست را اگه دید ، اون رویداد را به اون المنت متصل و اضافه میکنه . درسته؟
خیر. رویداد تعریف نمیشه که حالا حرکت بکنه یا نکنه. رویداد Click قبلا در کلاس تعریف شده، دیگه تعریف مجدد که نمیشه. رخداد در جایی به متدی متصل میشه که اون محل اتصال هم همونجا میمونه، مثلا در StackPanel ئه به متد فلان متصل شده، حالا این اتصال که بالا و پایین نمیره. نه بالا میره و نه پایین. همانطور که مثلا اگر جایی در کد i = 5 رو نوشتید، اون i = 5 در همون سطر میمونه، کد اش جابجا نمیشه، بالا و پایین نمیره که بره سمت بلوک های خارجی یا داخلی تر. سر جاش میمونه. رخداد ئه وقتی در یک المنت رخ داد برای پیدا کردن متدی که باید اجرا کنه بالا و پایین رو پیمایش می کنه، نه اینکه رخداد کفش اش رو بپوشه و پاشه بره بالا و یا پایین. رخداد سرجاش میمونه. Button.Click از جاش تکون نمیخوره، اما برای اینکه ببینه کدوم متد رو باید اجرا کنه المنت های بالاتر رو بررسی می کنه. پیمایش برای بررسی است، نه اینکه خودش حرکت کنه.

پس در کدی که مایکروسافت داده بود ، یعنی در کد زیر :

کد:
<Border Height="50" Width="300" BorderBrush="Gray" BorderThickness="1">
  <StackPanel Background="LightGray" Orientation="Horizontal" Button.Click="CommonClickHandler">
    <Button Name="YesButton" Width="Auto" >Yes</Button>
    <Button Name="NoButton" Width="Auto" >No</Button>
    <Button Name="CancelButton" Width="Auto" >Cancel</Button>
  </StackPanel>
</Border>

چرا رویداد Button.Click="CommonClickHandler" ، که در المنت StackPanel تعریف شد ، به سمت پایین اول حرکت کرد (یعنی اول ، به سمت المنت Button که فرزند StackPanel هست ، رفت) و بعد ، از اونجا به سمت بالا (به سمت ریشه که معمولا Window هست) حرکت میکنه؟
استراتژی حباب که نباید کاری به سمت پایین داشته باشه .
رخداد در Button ها داره رخ میده، نه StackPanel. اون Button.Click در StackPanel جابجا نمیشه، نه بالا میره و نه پایین. رخداد Button.Click در StackPanel رخ نمیده که پیمایش از اونجا شروع بشه. دارید از مقصد به سمت مبدا تفسیر می کنید، اگر کلیکی در Button رخ بده که StackPanel پاسخگو نیست، مبدا همون Button ئه. پیمایش از Button شروع میشه که اونم به سمت بالا پیمایش می کنه تا به StackPanel برسه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بله.

خیر. رویداد تعریف نمیشه که حالا حرکت بکنه یا نکنه. رویداد Click قبلا در کلاس تعریف شده، دیگه تعریف مجدد که نمیشه. رخداد در جایی به متدی متصل میشه که اون محل اتصال هم همونجا میمونه، مثلا در StackPanel ئه به متد فلان متصل شده، حالا این اتصال که بالا و پایین نمیره. نه بالا میره و نه پایین. همانطور که مثلا اگر جایی در کد i = 5 رو نوشتید، اون i = 5 در همون سطر میمونه، کد اش جابجا نمیشه، بالا و پایین نمیره که بره سمت بلوک های خارجی یا داخلی تر. سر جاش میمونه. رخداد ئه وقتی در یک المنت رخ داد برای پیدا کردن متدی که باید اجرا کنه بالا و پایین رو پیمایش می کنه، نه اینکه رخداد کفش اش رو بپوشه و پاشه بره بالا و یا پایین. رخداد سرجاش میمونه. Button.Click از جاش تکون نمیخوره، اما برای اینکه ببینه کدوم متد رو باید اجرا کنه المنت های بالاتر رو بررسی می کنه. پیمایش برای بررسی است، نه اینکه خودش حرکت کنه.


رخداد در Button ها داره رخ میده، نه StackPanel. اون Button.Click در StackPanel جابجا نمیشه، نه بالا میره و نه پایین. رخداد Button.Click در StackPanel رخ نمیده که پیمایش از اونجا شروع بشه. دارید از مقصد به سمت مبدا تفسیر می کنید، اگر کلیکی در Button رخ بده که StackPanel پاسخگو نیست، مبدا همون Button ئه. پیمایش از Button شروع میشه که اونم به سمت بالا پیمایش می کنه تا به StackPanel برسه.

سلامی مجدد استاد .
خیلی ممنون
بله . منظورم از حرکت کردن ، همون پیمایش هست .
اما من هنوز دقیق متوجه نشدم .

الان شما میگید که رخداد Button.Click در StackPanel رخ نمیده و این رخداد چون مربوط به Button هست ، پس این رخداد باید از یک Button شروع بشه (یعنی مبدا و Source این رویداد ، باید شی ButtonBase یا فرزندانش باشه) و حالا چون این رویداد ، استراتژیِ Bubble داره ، پس از Source اش که یه ButtonBase هست ، به سمت بالا ، یعنی به سمت Root Element که معمولا Window هست پیمایش میکنه و در مسیر پیمایش اش ، به هر کنترلی که از نوع ButtonBase یا فرزندانش هست ، روبه رو شد ، رویداد Click اش را به اون دلیگیت و متدی که ما مشخص کرده بودیم ، متصل و اضافه میکنه . درسته؟

اگه درسته :
1) پس چرا در کد پست شماره ی 192 (دو پست قبلی) ، پیمایش اش به سمت پایین هست؟ مگه پیمایش استراتژیِ Bubble ، به سمت بالا نیست؟

2) و در کد زیر :

کد:
    <Button Name="btnValed" HorizontalContentAlignment="Left" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="100, 100, 0 , 0" Width="500" Height="300" >
        <Button.Content>

            <TabControl Name="tabFarzand" ButtonBase.Click="TabItem_Click" Style="{StaticResource SimpleTabControl }" HorizontalAlignment="Left" Height="155" Margin="0,0,0,0" VerticalAlignment="Top" Width="500">
                <TabItem Header="TabItem">
                    <Grid Background="#FFE5E5E5">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="89*"/>
                            <ColumnDefinition Width="16*"/>
                            <ColumnDefinition Width="289*"/>
                        </Grid.ColumnDefinitions>
                        <Button Name="btnNaveh" Content="Button" HorizontalAlignment="Left" Height="39" Margin="153.25,49,0,0" VerticalAlignment="Top" Width="98" Grid.Column="2"/>
                        <CheckBox Name="chbxNaveh" Content="CheckBox" HorizontalAlignment="Left" Height="19" Margin="15.25,49,0,0" VerticalAlignment="Top" Width="112" Grid.Column="2"/>
                        <Label Name="lblNaveh" Content="abcdefg" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="20, 20,0,0"/>
                    </Grid>
                </TabItem>
                <TabItem Header="TabItem">
                    <Grid Background="#FFE5E5E5">
                        <ComboBox HorizontalAlignment="Left" Height="22" Margin="152,60,0,0" VerticalAlignment="Top" Width="132"/>
                    </Grid>
                </TabItem>
            </TabControl>

        </Button.Content>
    </Button>

چرا وقتی رویداد ButtonBase.Click را در TabControl ، ما Declare کردیم (چون منظورم از "تعریف" در پست قبلی ، همین Declare بود اما منظورم را شما متوجه نشدین) و استراتژی این رویداد هم که پیمایش به سمت بالاست (پیمایش به سمت اجداد تا به Root Element برسه) ، پس چرا اولا این رویداد ، به فرزندان TabControl متصل و اضافه میشه و این رویداد را به رویداد Click دو شیِ با نام های btnNaveh و chbxNaveh متصل و اضافه میکنه (یعنی برعکسِ استراتژیِ Bubble ، پیمایش به سمت پایین و به سمت فرزندان داره) و دوما چرا این رویداد کلیک را به کنترلِ والدِ TabControl ، یعنی به رویداد کلیک کنترل با نام btnValed که والد TabControl هست و از لحاظ پیمایش ، نسبت به کنترل TabControl ، در سمت بالا هست ، متصل و اضافه نمیکنه؟

3) و در کد زیر :

کد:
    <Button Name="btnValed" HorizontalContentAlignment="Left" VerticalContentAlignment="Top" Margin="20">

        <Grid Name="grdFarzand" Background="SkyBlue" Margin="10" >
            <Border Name="brdNaveh" Background="DarkOrange" Margin="30" MouseDown="myButton_MouseDown">
                <Border.Child>
                    <Button Name="btnNatijeh" Background="DarkKhaki" Margin="150,40, 0, 0" Width="50" Height="50"/>
                </Border.Child>
            </Border>
        </Grid>

    </Button>

که از همه عجیب تر هه .
اولا مثل کد قبلی ، چرا پیمایش به سمت پایین هه؟ یعنی وقتی رویداد UIElement.MouseDown که استراتژی Bubble داره (و پیمایش اش باید به سمت بالا باشه) ، در شی brdNaveh مون Declare شد ، فقط شی btnNatijeh که فرزندِ شیِ brdNaveh محسوب میشه را به اون رویدادمون متصل و اضافه کرد (یعنی پیمایش اش به سمت پایین بود) و شیِ btnValed که پدربزرگِ شیِ brdNaveh محسوب میشه را به این رویداد متصل نکرد (در صورتی که اگه مسیر پیمایش این رویداد اگه به سمت بالا میبود ، باید شی btnValed در کد بالا را به اون رویداد و متد متصل و اضافه میکرد) ؟
و دوما وقتی روی شیِ btnNatijeh کلیک چپ کنیم ، اون رویداد اجرا نمیشه (فقط در صورتی که کلیک راست یا اسکرول موس را به سمت پایین فشار بدیم و کلیک کنیم ، اجرا میشه) ولی روی شیِ brdNaveh که کلیک چپ هم کنیم ، اون رویداد اجرا میشه . چرا؟

4) من اگه کلا بخوام سیستم رویداد در wpf ، شبیه سیستم رویداد در windows form بشه ، یعنی وقتی برای یک شی ، رویدادی تنظیم میکنم ، فقط برای همون شی رویداد تنظیم بشه و به رویداد کنترل های فرزندان یا والدش کاری نداشته باشه ، در کدهای xaml ، راهی هست که این کار را انجام بدم؟


من که کاملا قاتی کردم .
یه پست دیگه هم در پست بعدی با یه سئوال دیگه هم میخوام بدم (چون در این پست شاید جا نشه) و سئوالش هم جداست . لطفا پست بعدی را هم جواب بدین .
خیلی ممنون استاد :rose:
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلامی مجدد
استاد ، در کد زیر (که همون کد آخر در پست بالا با اندکی تغییر هست) :

کد:
   <Button Name="btnValed" HorizontalContentAlignment="Left" VerticalContentAlignment="Top" Margin="20">

        <Grid Name="grdFarzand" Background="SkyBlue" >
            <Border Name="brdNaveh" Background="DarkOrange" Margin="30" MouseDown="myButton_MouseDown">
                <Border.Child>
                    <Button Name="btnNatijeh" Background="DarkKhaki" Margin="150,40, 0, 0" Width="50" Height="50"/>
                </Border.Child>
            </Border>
        </Grid>

    </Button>

وقتی پروپرتی های HorizontalContentAlignment="Left" و VerticalContentAlignment="Top" در شی btnValed را تنظیم کردم ، المنت فرزندش که شی grdFarzand باشه ، طبق چیزی که میخواستم به گوشه ی سمت چپ و بالا ، نسبت به شی btnValed منتقل شد اما شیِ grdFarzand ، کلِ محتوایِ شیِ btnValed را پوشش نداد و فقط بخشی از اون را پوشش داد . چرا و آیا با تنظیم پروپرتی (بدون اینکه template ای برای این کنترل ها بسازیم) میشه کاری کنیم که شیِ grdFarzand ، کلِ محتوای شیِ btnValed را احاطه کنه؟

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

the_king

مدیرکل انجمن
سلامی مجدد استاد .
خیلی ممنون
بله . منظورم از حرکت کردن ، همون پیمایش هست .
اما من هنوز دقیق متوجه نشدم .

الان شما میگید که رخداد Button.Click در StackPanel رخ نمیده و این رخداد چون مربوط به Button هست ، پس این رخداد باید از یک Button شروع بشه (یعنی مبدا و Source این رویداد ، باید شی ButtonBase یا فرزندانش باشه) و حالا چون این رویداد ، استراتژیِ Bubble داره ، پس از Source اش که یه ButtonBase هست ، به سمت بالا ، یعنی به سمت Root Element که معمولا Window هست پیمایش میکنه و در مسیر پیمایش اش ، به هر کنترلی که از نوع ButtonBase یا فرزندانش هست ، روبه رو شد ،
بله.
رویداد Click اش را به اون دلیگیت و متدی که ما مشخص کرده بودیم ، متصل و اضافه میکنه . درسته؟
خیر. متصل و اضافه کردن رو از کجا آوردید؟ اجرا می کنه، نه اینکه متصل کنه. پیمایش می کنه که ببینه چی رو باید اجرا کنه، نه اینکه چی رو باید متصل کنه.
اگه درسته :
1) پس چرا در کد پست شماره ی 192 (دو پست قبلی) ، پیمایش اش به سمت پایین هست؟ مگه پیمایش استراتژیِ Bubble ، به سمت بالا نیست؟
فکر نکنم در مفهوم بالا و پایین اختلاف نظری داشته باشیم، بالای Button المنت های والد Button قرار داره و در سمت پایین اش، فرزندان Button که من در پست 192 نمی بینم ولی انگار شما می بینید.
به سمت بالا نیست؟ لطفا مراحلی که در پیمایش طی می کنه مرور کنید، بگید یک دکمه بود رویش کلیک شد و برای پیدا کردن متد ای که باید اجرا بشه به سمت بالا حرکت نکرد و به سمت پایین یعنی فرزندان Button که من نمیدونم کجا هستند حرکت کرد و از کدوم المنت ها عبور کرد. طبعا اگر به سمت بالا نباشه "Button.Click="CommonClickHandler در مسیرش نیست و وجودش تاثیری نداره و اجرا نمیشه.

2) و در کد زیر :

کد:
    <Button Name="btnValed" HorizontalContentAlignment="Left" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="100, 100, 0 , 0" Width="500" Height="300" >
        <Button.Content>

            <TabControl Name="tabFarzand" ButtonBase.Click="TabItem_Click" Style="{StaticResource SimpleTabControl }" HorizontalAlignment="Left" Height="155" Margin="0,0,0,0" VerticalAlignment="Top" Width="500">
                <TabItem Header="TabItem">
                    <Grid Background="#FFE5E5E5">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="89*"/>
                            <ColumnDefinition Width="16*"/>
                            <ColumnDefinition Width="289*"/>
                        </Grid.ColumnDefinitions>
                        <Button Name="btnNaveh" Content="Button" HorizontalAlignment="Left" Height="39" Margin="153.25,49,0,0" VerticalAlignment="Top" Width="98" Grid.Column="2"/>
                        <CheckBox Name="chbxNaveh" Content="CheckBox" HorizontalAlignment="Left" Height="19" Margin="15.25,49,0,0" VerticalAlignment="Top" Width="112" Grid.Column="2"/>
                        <Label Name="lblNaveh" Content="abcdefg" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="20, 20,0,0"/>
                    </Grid>
                </TabItem>
                <TabItem Header="TabItem">
                    <Grid Background="#FFE5E5E5">
                        <ComboBox HorizontalAlignment="Left" Height="22" Margin="152,60,0,0" VerticalAlignment="Top" Width="132"/>
                    </Grid>
                </TabItem>
            </TabControl>

        </Button.Content>
    </Button>

چرا وقتی رویداد ButtonBase.Click را در TabControl ، ما Declare کردیم (چون منظورم از "تعریف" در پست قبلی ، همین Declare بود اما منظورم را شما متوجه نشدین)
من هم منظور شما متوجه شدم و هم اینکه معنی تعریف کردن، اعلان کردن، declare کردن و define کردن رو اشتباه بکار می برید رو متوجه شدم. تاپیک event - C# Reference رو باز کنید و ببینید declare رخداد یعنی چی. declare کردن یک رخداد یعنی تعریف کردنش، یعنی اضافه کردن رخداد به کلاس، اینترفیس و کلا تعریف کردن ماهیت رخداد. اصلا و ابدا ربطی به متصل کردنش نداره. Click یکبار در کلاس declare شده، اتصال اش بعدا انجام میشه، هزار بار هم که Click رو متد هایی متصل کنید کار تون تعریف کردن یا declare نیست، تعریف نیست، اعلان نیست.
// Declare the delegate (if using non-generic pattern).
public delegate void SampleEventHandler(object sender, SampleEventArgs e);

// Declare the event.
public event SampleEventHandler SampleEvent;
شما در TabControl اون ButtonBase.Click رو Declare نمی کنید، تعریف نمی کنید، اعلان نمی کنید. مقدار برای رخداد Set میشه، مقدار بهش Assign میشه، Handler بهش Associate میشه، Handler بهش Add میشه، در XAML ئه Describe میشه، توصیف میشه، هیچکدوم از اینها نه تعریف کردن هستند و نه اعلان کردن.

و استراتژی این رویداد هم که پیمایش به سمت بالاست (پیمایش به سمت اجداد تا به Root Element برسه) ، پس چرا اولا این رویداد ، به فرزندان TabControl متصل و اضافه میشه و این رویداد را به رویداد Click دو شیِ با نام های btnNaveh و chbxNaveh متصل و اضافه میکنه (یعنی برعکسِ استراتژیِ Bubble ، پیمایش به سمت پایین و به سمت فرزندان داره) و دوما چرا این رویداد کلیک را به کنترلِ والدِ TabControl ، یعنی به رویداد کلیک کنترل با نام btnValed که والد TabControl هست و از لحاظ پیمایش ، نسبت به کنترل TabControl ، در سمت بالا هست ، متصل و اضافه نمیکنه؟
مطالب صفحه Routed Events Overview - WPF رو یکبار درست مطالعه کنید و ببینید پیمایش به هر جهتی که باشه برای چه هدفی است؟ هدف اجرا کردن متد ئه یا هدف متصل کردن به رخداد ئه. از دو حالت که خارج نیست، یا با هدف اجرا کردن متد ئه، یا با هدف متصل کردن به رخداد. فرض کنیم که طبق نظر شما پیمایش برای متصل کردن و اضافه کردن به رخداد باشه.
این پیمایش چه زمانی انجام میشه؟ دو حالت داره، یا باید موقع توصیف کردن ButtonBase.Click در TabControl این پیمایش انجام میشده یا موقع کلیک کردن روی Button. یکی از ایندو حالت ئه.
حالت اول، اگر موقع توصیف کردن ButtonBase.Click باشه، موقع تفسیر XAML انجام میشه، پس اگر بعدا موقع اجرا با کد نویسی دکمه ای به عنوان فرزند به TabControl اضافه کنید دیگه ButtonBase.Click برای اون Button جدید اجرا نمیشه، چون توصیف ButtonBase.Click و پیمایش اش در گذشته صورت گرفته. اما رخداد برای Button جدید هم اجرا میشه و این حالت نمیتونه درست باشه.
حالت دوم، اگر موقع کلیک کردن روی Button پیمایش انجام میشه. میدونیم که اتصال یک متد به رخداد میتونه چندین بار صورت بگیره و موقع وقوع رخداد یک متدی بیشتر از یکبار اجرا بشه.
پس انتظار داریم که با هر بار کلیک روی Button ها که منجر به پیمایش میشه، یکبار دیگه ButtonBase.Click به اون متد متصل بشه و تعداد وقوع رخداد هی بیشتر و بیشتر بشه، بجای یکبار چند بار اجرا بشه. که این امرهم اتفاق نمی افته و اشتباه ئه. فقط یکبار اجرا میشه.

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

4) من اگه کلا بخوام سیستم رویداد در wpf ، شبیه سیستم رویداد در windows form بشه ، یعنی وقتی برای یک شی ، رویدادی تنظیم میکنم ، فقط برای همون شی رویداد تنظیم بشه و به رویداد کنترل های فرزندان یا والدش کاری نداشته باشه ، در کدهای xaml ، راهی هست که این کار را انجام بدم؟
اگر میخواهید از Routed Events استفاده نکنید پس از Routed Events استفاده نکنید.
 

SajjadKhati

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

الان استاد ، در کد زیر :

کد:
    <Button Name="btnLevel_1" Margin="20">
        <Button  Name="btnLevel_2" Width="650" Height="300" Background="DarkCyan" HorizontalContentAlignment="Left" VerticalContentAlignment="Top">
            <Button ButtonBase.Click="CommonClickHandler"  Name="btnLevel_3" Margin="50,50" Width="550" Height="200" Background="DarkKhaki" HorizontalContentAlignment="Left" VerticalContentAlignment="Top">
                <Button  Name="btnLevel_4" Margin="70, 30" Width="400" Height="130" Background="DarkMagenta" HorizontalContentAlignment="Left" VerticalContentAlignment="Top">

                </Button>
            </Button>
        </Button>
    </Button>

و رویداد سی شارپ اش هم :

کد:
        private void CommonClickHandler(object sender, RoutedEventArgs e)
        {
            FrameworkElement senderElement = sender as FrameworkElement;
            FrameworkElement sourceElement = e.Source as FrameworkElement;
            Debug.WriteLine("sender fired :  {0}  ....  Source : {1}", new string[] { senderElement.Name, sourceElement.Name });

        }

دیگه همه از نوع Button و در 4 سطح (پدر و فرزندی) هستند و وقتی رویداد ButtonBase.Click که از نوع Routed Event هست و استراتژی حباب داره (باید از source اش شروع بشه و به سمت بالا پیمایش کنه) را در کنترل btnLevel_3 گذاشتم ، بجای اینکه مسیر پیمایش اش به سمت بالا (به سمت btnLevel_2 و btnLevel_1) باشه ، به سمت پایین (سمت btnLevel_4) هست .

اول اینکه چرا استراتژی حباب در کد بالا ، به سمت پایین پیمایش میکنه؟
الان پس منظورم از مثال های قبلی را متوجه شدین؟ منظورم همین بود و در این کد چون همه از یه جنس ButtonBase هستن ، کاملا مشخصه .
دوم اینکه وقتی روی کنترل btnLevel_3 کلیک میکنم ، در پنجره ی output ، هر دو نوع sender و e.Source ، شی btnLevel_3 هستند که مشکلی نیست . اما وقتی روی کنترل btnLevel_4 کلیک میکنم ، شی sender اش را btnLevel_3 اعلام میکنه و شی e.Source اش را btnLevel_4 اعلام میکنه . چرا؟
مگه نباید برعکس باشه؟ یعنی وقتی روی کنترل btnLevel_4 کلیک میکنیم ، مگه نباید sender ، همون شی ای که رویداد اش اجرا شد ، یعنی همون شی btnLevel_4 باشه (sender باشه که تغییر میکنه) و این e.Source باشه که ثابت بمونه و همون شیِ مبدا (حالا btnLevel_3 یا btnLevel_4 که فعلا با این قضیه ، نمیدونم مبدا کدوم هه چون مسیر پیمایش رو هنوز متوجه نشدم) باشه و ثابت بمونه؟

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

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

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

درباره ی اینکه گفتید :
"اگر میخواهید از Routed Events استفاده نکنید پس از Routed Events استفاده نکنید."
خوب الان اگه بخوام از رویداد Click در Button استفاده کنم ، فقط همین رویداد که از نوع Routed Events هست ، وجود داره . رویداد Click ئه دیگه ای از نوعی بجز نوعِ Routed Events وجود نداره .
در این صورت باید چی کار کرد؟

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

استاد ، چیدمان Content در Button را من آخر متوجه نشدم .
در کدی که در بالا (در همین پست) دادم ، نگاه کنید .
به زور و شانسی ، هر پروپرتی را تست میکردم که این 4 تا دکمه را بتونم تقریبا داخل هم با Margin ای به یک اندازه قرار بدم اما همونطور که میبینید شانسی هه و Margin و کلا چیدمان هر کدوم با هم متفاوت هستند .
چجوری میشه کد بالا را جوری نوشت که این 4 تا Button ، با Margin یا Padding ای دقیقا یک اندازه ، درون هم قرار بگیرن (بدون نوشتن Template)؟
یعنی چیدمان 4 تا دکمه در کد بالا ، مثل چیدمان Border ها در کد پایین (یعنی بصورت دقیق) بشه؟ :

کد:
    <Border Margin="30" BorderThickness="2" BorderBrush="Blue">
        <Border Margin="30" BorderThickness="2" BorderBrush="Blue">
            <Border Margin="30" BorderThickness="2" BorderBrush="Blue">
                <Border Margin="30" BorderThickness="2" BorderBrush="Blue">

                </Border>
            </Border>
        </Border>
    </Border>
 

the_king

مدیرکل انجمن
سلامی مجدد
استاد ، در کد زیر (که همون کد آخر در پست بالا با اندکی تغییر هست) :

کد:
   <Button Name="btnValed" HorizontalContentAlignment="Left" VerticalContentAlignment="Top" Margin="20">

        <Grid Name="grdFarzand" Background="SkyBlue" >
            <Border Name="brdNaveh" Background="DarkOrange" Margin="30" MouseDown="myButton_MouseDown">
                <Border.Child>
                    <Button Name="btnNatijeh" Background="DarkKhaki" Margin="150,40, 0, 0" Width="50" Height="50"/>
                </Border.Child>
            </Border>
        </Grid>

    </Button>

وقتی پروپرتی های HorizontalContentAlignment="Left" و VerticalContentAlignment="Top" در شی btnValed را تنظیم کردم ، المنت فرزندش که شی grdFarzand باشه ، طبق چیزی که میخواستم به گوشه ی سمت چپ و بالا ، نسبت به شی btnValed منتقل شد اما شیِ grdFarzand ، کلِ محتوایِ شیِ btnValed را پوشش نداد و فقط بخشی از اون را پوشش داد . چرا و آیا با تنظیم پروپرتی (بدون اینکه template ای برای این کنترل ها بسازیم) میشه کاری کنیم که شیِ grdFarzand ، کلِ محتوای شیِ btnValed را احاطه کنه؟

خیلی ممنون استاد
شما خودتون نمی خواستید کل محتوای کادر Content (نه کادر Button) رو پوشش بده، چون VerticalContentAlignment و HorizontalContentAlignment رو بجای Stretch روی Top و Left تنظیم کردید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
شما خودتون نمی خواستید کل محتوای کادر Content (نه کادر Button) رو پوشش بده، چون VerticalContentAlignment و HorizontalContentAlignment رو بجای Stretch روی Top و Left تنظیم کردید.

سلامی مجدد
آها خیلی ممنون استاد :rose:
یعنی باید HorizontalContentAlignment="Stretch" و VerticalContentAlignment="Stretch" را روی Stretch تنظیم کنیم و بعد Margin یا Padding اش را مشخص کنیم؟
فرق Strech با بقیه اینه که محتوا را کِش میاره تا کلِ فضایِ محتوای اون کنترل را پوشش بده؟
دلیل اینکه توی Border لازم نیست تا پروپرتیِ HorizontalContentAlignment و VerticalContentAlignment اش را به Stretch تنظیم کنیم تا کنترلی که در داخل اش میذاریم (به عنوان Content)، کلِ فضای محتوا اش را پوشش بده ولی برای کنترل Button مجبوریم این کار را کنیم ، به این دلیل هه که در ContentPresenter ئه مربوط به کنترل Button ، برای ContentAlignment اش ، از مقدار Stretch استفاده نشد اما برای Border استفاده شد؟

سئوال قبلی (پست 197) را هم بی زحمت جواب میدین؟
 

the_king

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

الان استاد ، در کد زیر :

کد:
    <Button Name="btnLevel_1" Margin="20">
        <Button  Name="btnLevel_2" Width="650" Height="300" Background="DarkCyan" HorizontalContentAlignment="Left" VerticalContentAlignment="Top">
            <Button ButtonBase.Click="CommonClickHandler"  Name="btnLevel_3" Margin="50,50" Width="550" Height="200" Background="DarkKhaki" HorizontalContentAlignment="Left" VerticalContentAlignment="Top">
                <Button  Name="btnLevel_4" Margin="70, 30" Width="400" Height="130" Background="DarkMagenta" HorizontalContentAlignment="Left" VerticalContentAlignment="Top">

                </Button>
            </Button>
        </Button>
    </Button>

و رویداد سی شارپ اش هم :

کد:
        private void CommonClickHandler(object sender, RoutedEventArgs e)
        {
            FrameworkElement senderElement = sender as FrameworkElement;
            FrameworkElement sourceElement = e.Source as FrameworkElement;
            Debug.WriteLine("sender fired :  {0}  ....  Source : {1}", new string[] { senderElement.Name, sourceElement.Name });

        }

دیگه همه از نوع Button و در 4 سطح (پدر و فرزندی) هستند و وقتی رویداد ButtonBase.Click که از نوع Routed Event هست و استراتژی حباب داره (باید از source اش شروع بشه و به سمت بالا پیمایش کنه) را در کنترل btnLevel_3 گذاشتم ، بجای اینکه مسیر پیمایش اش به سمت بالا (به سمت btnLevel_2 و btnLevel_1) باشه ، به سمت پایین (سمت btnLevel_4) هست .
روی دکمه btnLevel_1 کلیک می کنید، به سمت بالا و والدین اش پیمایش می کنه و چیزی برای اجرا کردن برای رخداد کلیک پیدا نمی کنه و CommonClickHandler هم اجرا نمیشه.
روی دکمه btnLevel_2 کلیک می کنید، به سمت بالا و والدین اش پیمایش می کنه و چیزی برای اجرا کردن برای رخداد کلیک پیدا نمی کنه و CommonClickHandler هم اجرا نمیشه.
روی دکمه btnLevel_3 کلیک می کنید، به سمت بالا و والدین اش پیمایش می کنه و ButtonBase.Click رو در همون شروع پیمایش در المنت خودش می بینه و CommonClickHandler اجرا میشه.
روی دکمه btnLevel_4 کلیک می کنید، به سمت بالا و والدین اش پیمایش می کنه و ButtonBase.Click رو در المنت والدش پیدا می کنه و CommonClickHandler اجرا میشه.

چه چیزی در پیمایش این رخداد ها به سمت پایین بود؟ روی btnLevel_1 که کلیک می کنید ButtonBase.ClickButtonBase.Click رو در پایین و فرزندانش پیدا می کنه و CommonClickHandler اجرا میشه؟

اول اینکه چرا استراتژی حباب در کد بالا ، به سمت پایین پیمایش میکنه؟
فرض سوال طبق معمول اشتباه ئه، سوال با فرض اشتباه هم که جواب نداره.

الان پس منظورم از مثال های قبلی را متوجه شدین؟ منظورم همین بود و در این کد چون همه از یه جنس ButtonBase هستن ، کاملا مشخصه .
دوم اینکه وقتی روی کنترل btnLevel_3 کلیک میکنم ، در پنجره ی output ، هر دو نوع sender و e.Source ، شی btnLevel_3 هستند که مشکلی نیست . اما وقتی روی کنترل btnLevel_4 کلیک میکنم ، شی sender اش را btnLevel_3 اعلام میکنه و شی e.Source اش را btnLevel_4 اعلام میکنه . چرا؟
مگه نباید برعکس باشه؟ یعنی وقتی روی کنترل btnLevel_4 کلیک میکنیم ، مگه نباید sender ، همون شی ای که رویداد اش اجرا شد ، یعنی همون شی btnLevel_4 باشه (sender باشه که تغییر میکنه) و این e.Source باشه که ثابت بمونه و همون شیِ مبدا (حالا btnLevel_3 یا btnLevel_4 که فعلا با این قضیه ، نمیدونم مبدا کدوم هه چون مسیر پیمایش رو هنوز متوجه نشدم) باشه و ثابت بمونه؟
ثابت بودن و نبودن رو نمیدونم از کجا میارید، جایی در مورد ثابت بودن اینها مطلب خوندید؟ از خودتون قاعده اختراع نکنید.
نه، منبع وقوع رخداد جایی است که رخداد رخ داده، که کلیک شدن روی btnLevel_4 ئه، کلیک شدن روی btnLevel_3 که اتفاق نیافتاده. منبع بروز رخداد btnLevel_4 ئه، اما نمیتونه خودش گزارش اش کنه، sender نمیتونه باشه،
چون در btnLevel_4 برای گزارش رخداد Click متد مشخص نشده، در ادامه پیمایش وقتی میرسه به btnLevel_3 تازه متد برای گزارش شدن رخداد پیدا شده و گزارش دهنده رخداد المنت btnLevel_3 میشه، برای همین sender ئه btnLevel_3 شده.

بله .
Declare ، رو من آخر متوجه نشدم چه مفهومی داره . خیلی جاها به معنای تعریف کردن که شما گفتید به کار میبرن . اما خیلی جاهای دیگه به معنای فراخونی (مثلا فراخونی متد) به کار میبرن که بعدا اگه به پستم خورد ، براتون میذارم . خودمم متوجه نشدم آخر قضیه ی Declare چجوری هه .
در انگلیسی مشکل دارید، در فارسی چرا قاطی می کنید? شما میگید در جاهای دیگری declare به معنای فراخوانی متد بکار رفته، بعد برای تعریف کردن معنی declare رو بکار می برید؟ معنی کلمات فارسی رو که باید متوجه بشید.
فراخوانی کردن با تعریف کردن یک معنی میده؟

درباره ی اینکه گفتید :
"اگر میخواهید از Routed Events استفاده نکنید پس از Routed Events استفاده نکنید."
خوب الان اگه بخوام از رویداد Click در Button استفاده کنم ، فقط همین رویداد که از نوع Routed Events هست ، وجود داره . رویداد Click ئه دیگه ای از نوعی بجز نوعِ Routed Events وجود نداره .
در این صورت باید چی کار کرد؟
اینکه رویداد Click توانایی routing داشته باشه که مشکلی نیست، routing اش اختیاری است، می توانید بگید نکنه.
باید تاپیک Routed Events رو بخونید، نخوندید که، اگه میخوندید سوال نمی پرسیدید. براتون مثال کد هم نوشته بود.

استاد ، چیدمان Content در Button را من آخر متوجه نشدم .
در کدی که در بالا (در همین پست) دادم ، نگاه کنید .
به زور و شانسی ، هر پروپرتی را تست میکردم که این 4 تا دکمه را بتونم تقریبا داخل هم با Margin ای به یک اندازه قرار بدم اما همونطور که میبینید شانسی هه و Margin و کلا چیدمان هر کدوم با هم متفاوت هستند .
چجوری میشه کد بالا را جوری نوشت که این 4 تا Button ، با Margin یا Padding ای دقیقا یک اندازه ، درون هم قرار بگیرن (بدون نوشتن Template)؟
یعنی چیدمان 4 تا دکمه در کد بالا ، مثل چیدمان Border ها در کد پایین (یعنی بصورت دقیق) بشه؟ :

کد:
    <Border Margin="30" BorderThickness="2" BorderBrush="Blue">
        <Border Margin="30" BorderThickness="2" BorderBrush="Blue">
            <Border Margin="30" BorderThickness="2" BorderBrush="Blue">
                <Border Margin="30" BorderThickness="2" BorderBrush="Blue">

                </Border>
            </Border>
        </Border>
    </Border>
نمیفهمم چی میگید، ظاهرش مگه چطوری میشه که میگید شانسی ئه؟
 

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

بالا