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

SajjadKhati

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

استاد ، پست 58 که جواب بله دادید به سئوالم ، خوب سئوالم این بود که کدهای xml و سی شارپ ای که در پست 55 دادم ، با هم برابر هستند یا نه؟
که گفتید بله برابرند .
اما اون پست که کد سی شارپ اش کامل نبود . شی Style داخلش نبود (اما در کد xml ، تگ Style بود) . توی کد سی شارپ در پست 55 ، فقط شی Border بود .
حالا در پست 59 که شی Style را هم برای کد سی شارپ در نظر گرفتم و نوشتم ، برابر با کد xml شد؟
متوجه شدین منظورم رو دیگه؟
 

the_king

مدیرکل انجمن
استاد ، پست 58 که جواب بله دادید به سئوالم ، خوب سئوالم این بود که کدهای xml و سی شارپ ای که در پست 55 دادم ، با هم برابر هستند یا نه؟
که گفتید بله برابرند .
شما در سوال اول تون پرسیدید :
آیا مثلا SolidColorBrush ای که در کد بالا نوشت ، برابر با این هست که مثلا یه شی به عضو کلاس ResourceDictionary اضافه کرده باشیم که مقدار key اش رشته ی MyBrush هست و مقدار value اش شی ای از SolidColorBrush هست که مقدار پروپرتی Color از این شی ، Gold هست؟
یعنی آیا این جوری هست؟ :

کد:
            this.btnTest1.Resources = new ResourceDictionary();
            SolidColorBrush solidColorBrush = new SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("Gold"));
            this.btnTest1.Resources.Add("MyBrush", solidColorBrush);

در خط بعدی (در کد اول) که Style هست هم به همین صورت هست؟ یعنی Style را به عنوان عضو دوم از کالکشن ResourceDictionary در بالا میشه حساب کرد؟
که گفتید اون بخش کد کامل رو بذارم کنار و باقیش رو پاسخ بدم که من هم جواب دادم بله.
در مورد کد کامل هم که در مورد ابهام در سوال تون جواب دادم و مثل همه سوالات دیگری که ازتون در مورد منبع مطلب کردم و منبعی برایش معرفی نکردید بی جواب گذاشتید.
اما اون پست که کد سی شارپ اش کامل نبود . شی Style داخلش نبود (اما در کد xml ، تگ Style بود) . توی کد سی شارپ در پست 55 ، فقط شی Border بود .
متوجه شدین منظورم رو دیگه؟
کد #C کامل یعنی چی؟ یه لینک بدید بگید در فلان جا کد #C کامل تعریف شده. چرا سوال هایی که من میکنم رو جواب نمیدید؟
حالا در پست 59 که شی Style را هم برای کد سی شارپ در نظر گرفتم و نوشتم ، برابر با کد xml شد؟
شما اگه دقت کنید در پست 59 تون Style ای در کد #C تعریف نکردید. چه برسه به اینکه به Resources اضافه اش کنید.
 

SajjadKhati

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

که گفتید اون بخش کد کامل رو بذارم کنار و باقیش رو پاسخ بدم که من هم جواب دادم بله.
در مورد کد کامل هم که در مورد ابهام در سوال تون جواب دادم و مثل همه سوالات دیگری که ازتون در مورد منبع مطلب کردم و منبعی برایش معرفی نکردید بی جواب گذاشتید.

کد #C کامل یعنی چی؟ یه لینک بدید بگید در فلان جا کد #C کامل تعریف شده. چرا سوال هایی که من میکنم رو جواب نمیدید؟

جواب دادم که استاد.
گفتم منظورم را بد متوجه شدین.
در واقع ، من منظورم را بد رسوندم.
هنوز هم فکر کنم دقیق متوجه ی منظورم نشدین.


شما اگه دقت کنید در پست 59 تون Style ای در کد #C تعریف نکردید. چه برسه به اینکه به Resources اضافه اش کنید.

در پست شماره ی ۵۹ ، تگ page.Resurce تعریف شده دیگه .
مگه شماره بندی پست ها ، براتون مشخص نیست؟
منظورم پست زیر هست :

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

the_king

مدیرکل انجمن
در پست شماره ی ۵۹ ، تگ page.Resurce تعریف شده دیگه .
مگه شماره بندی پست ها ، براتون مشخص نیست؟
منظورم پست زیر هست :
سئوالات و مباحث WPF
عرض کردم Style در کد #C کو، Style در کد #C تون. تگ <Page.Resources> که در کد #C نیست، در XML ئه.
بله. همون پست. من در کد #C شما جایی که Style ای تعریف کردید نمی بینم، یه چیزی مثل new Style توش مخفی کردید که من نمی بینم؟
code.png
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
عرض کردم Style در کد #C کو، Style در کد #C تون. تگ <Page.Resources> که در کد #C نیست، در XML ئه.
بله. همون پست. من در کد #C شما جایی که Style ای تعریف کردید نمی بینم، یه چیزی مثل new Style توش مخفی کردید که من نمی بینم؟
مشاهده پیوست 113400

بله .
ببخشید .
حواسم نبود :

کد:
            SolidColorBrush solidColorBrush = new SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("Gold"));
            Setter setter = new Setter(DependencyProperty.Register("Background",typeof(Brush), typeof(Border)), (System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("Blue"), "Border");
            Style style = new Style(typeof(Border));
            style.Setters.Add(setter);

            this.myPage1.Resources = new ResourceDictionary();
            this.myPage1.Resources.Add("MyBrush", solidColorBrush);
            this.myPage1.Resources.Add("PageBackground", style);

کد بالا الان برابر با کد xml در پست 59 هست؟
اگه نیست ، اصلاح میکنید؟

به مفهوم Key دقت کنید. شما یک Style میسازید، مثلا با کلید PageBackground هم درج اش می کنید. این Key متعلق به Style که نیست. برای Style ها Key معنی نداره، Style.Key نداریم. همچین مشخصه ای نداره، همچین فیلدی نداره، کاربرد Style ارتباطی با Key نداره. اون Key از دیکشنری ئه میاد، ما صفت Key رو برای خود شی Style که مقدار دهی نمی کنیم، برای اون مدخل ثبت می کنیم که این Style رو میخواد به عنوان مقدار بگیره. Key یک سمت ئه و Value یک سمت دیگه مدخل. Style ئه Value بوده، x:Key رو داریم در Value می نویسیم، اگر پیشوند نداشت میشد جزو خود Value که برای Style هم کاربرد و معنی نداره.
برای همین attribute ئه x:Key شده. با attribute ای مثل TargetType فرق داره چون TargetType جزئی از Style ئه، Style.TargetType هست و معنی داره. جزئی از خود Value ئه.
اینجور جاها اون پیشوند مشخص میکنه که این attribute ئه Key که برای خود تگ کاربردی نداره و معلوم نیست از کجا سر و کله اش پیدا شده، برای چه منظوریه و به چی ربط داره.

خیلی ممنون استاد .
پس هر وقت عضوی از شی ای (یا در واقع اتریباتس ای از تگ ای) (مثل Key) را میخوایم مقداردهی کنیم که اون عضوِ اتریباتس (مثل SolidColorBrush) ، درون اون تگ (یا در واقع درون کلاس اون تگ) موجود نیست ، از پیشوند استفاده میکنیم . درسته؟
حالا نمیدونم چرا همش از پیشوند x استفاده میشه . اونجا چند تا پیشوند دیگه مثل d و mc و ... هم تعریف شده . چرا از اونها استفاده نمیشه؟
 

the_king

مدیرکل انجمن
بله .
ببخشید .
حواسم نبود :
کد:
            SolidColorBrush solidColorBrush = new SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("Gold"));
            Setter setter = new Setter(DependencyProperty.Register("Background",typeof(Brush), typeof(Border)), (System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("Blue"), "Border");
            Style style = new Style(typeof(Border));
            style.Setters.Add(setter);

            this.myPage1.Resources = new ResourceDictionary();
            this.myPage1.Resources.Add("MyBrush", solidColorBrush);
            this.myPage1.Resources.Add("PageBackground", style);

کد بالا الان برابر با کد xml در پست 59 هست؟
نیست، در مورد DependencyProperty.Register توضیح دادم، برنامه من که نیست که اصلاحش کنم. مجددا پاسخ ام رو بخونید.
در ضمن برای Background ای که از نوع Brush ئه چه مقداری در نظر گرفته اید؟ Color ئه Blue رو میخواهید بجای Brush در Background ست کنید؟ امتحان کنید ببینید می توانید در یک Brush مقدار Color بدید. Brushes.Blue ئه، به همین سادگی. چرا با ColorConverter؟ مگه Colors.Blue رو نمی خواهید؟ "Blue" رو از متغیر و منبع نامعلومی نمیخونید که قبل از اجرا ندونید مقدارش چیه، مقدار ثابت دارید میدید، چرا با تبدیل؟

خیلی ممنون استاد .
پس هر وقت عضوی از شی ای (یا در واقع اتریباتس ای از تگ ای) (مثل Key) را میخوایم مقداردهی کنیم که اون عضوِ اتریباتس (مثل SolidColorBrush) ، درون اون تگ (یا در واقع درون کلاس اون تگ) موجود نیست ، از پیشوند استفاده میکنیم . درسته؟
حالا نمیدونم چرا همش از پیشوند x استفاده میشه . اونجا چند تا پیشوند دیگه مثل d و mc و ... هم تعریف شده . چرا از اونها استفاده نمیشه؟
بله. هر پیشوندی برای منظوری تعریف شده، وقتی x:Key برای مشخص کردن کلید در نظر گرفته شده طبعا با پیشوند دیگری اون معنی رو نمیده.
همونطور که d:DataContext با همون پیشوند d کاربرد داره، با پیشوند x تعریف و کارکرد خاصی نداره.
هر چقدر اون atrribute های مرتبط با پیشوند استفاده بیشتری داشته باشه پیشوند اش رو هم بیشتر می بینید. دلیلی نداره که attribute های مرتبط رو در پیشوند های جداگانه توزیع کنند تا عدالت در تعداد رعایت باشه.
از mc اصلا استفاده نشه، قهر که نمی کنه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
در Resources دو تا مدخل، آیتم، عضو یا هر چیزی که اسمش رو بذارید ثبت شده، که کلید شون MyBrush و PageBackground ئه. نوع شون هم SolidColorBrush و Style ئه.

خیلی ممنون استاد .
آها .
پس منظور از Entry یا مدخل ، همون آیتم های دیکشنری هستند؟

اون Setter جزو مدخل های Resources که نیست، جزئی از Style ئه. شما در کد #C تون اصلا Style نساختید. PageBackground قرار بود Style باشه، نه Setter

بله .

در ضمن Background جزو مشخصه های موجود در Border هست. شما با DependencyProperty.Register چیزی رو ثبت می کنید که قبلا نبوده و جدید ئه. Background رو که نمیشه از نو ثبت کرد.

منظورتون را متوجه نمیشم .

باید سراغ اون DependencyProperty بروید که قبلا برای Background ثبت شده. BackgroundProperty که دنبالش هستید یک فیلد static readonly ئه، با Border.BackgroundProperty بهش دسترسی دارید.
Brushes.Blue هم که مورد مشخصی است.

متوجه نمیشم که چی کار باید کنم .متد سازنده ی Setter ، شی ای از DependencyProperty میخواد . این کلاس هم که متد سازنده نداره . تنها عضوی که شی DependencyProperty را برمیگردونه ، عضو استاتیک متد Register درون همین کلاس هست (یعنی DependencyProperty.Register ) . الان منظورتون اینه که میخوام شی ای از این کلاس بگیرم ، از متد Register استفاده نکنم؟
اگه منظورتون اینه ، پس چی کار کنم؟

اون کدی که در پست قبلی دادم را اگه درست کنید ، ممنون میشم . من بلد نیستم . فعلا همین قدر میدونم که انجام دادم .
 
آخرین ویرایش:

the_king

مدیرکل انجمن
خیلی ممنون استاد .
متوجه نمیشم که چی کار باید کنم .متد سازنده ی Setter ، شی ای از DependencyProperty میخواد . این کلاس هم که متد سازنده نداره . تنها عضوی که شی DependencyProperty را برمیگردونه ، عضو استاتیک متد Register درون همین کلاس هست (یعنی DependencyProperty.Register ) . الان منظورتون اینه که میخوام شی ای از این کلاس بگیرم ، از متد Register استفاده نکنم؟
اگه منظورتون اینه ، پس چی کار کنم؟
جواب هایی که میدم رو واقعا میخونید؟ در جوابم Border.BackgroundProperty به اون درازی رو نمی بینید؟ Border.BackgroundProperty از چه نوع داده ای است؟ از نوع DependencyProperty نیست؟
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
جواب هایی که میدم رو واقعا میخونید؟ در جوابم Border.BackgroundProperty به اون درازی رو نمی بینید؟ Border.BackgroundProperty از چه نوع داده ای است؟ از نوع DependencyProperty نیست؟

:green:
خیلی ممنون استاد .
کلا هر کلاس ، در اعضای استاتیکش ، برای پروپرتی هاش ، فیلدی بنام PropertyName+Property داره ، که شی DependencyProperty را برمیگردونه؟
این کلاس DependencyProperty ، کار همون کلاس PropertyInfo را نمیکنه؟

پس با این اوضاع ، معادل کد سی شارپِ اون کد xml ، کد زیر میشه؟ (درباره ی اون Brushes.Blue هم خیلی ممنون) :

کد:
            SolidColorBrush solidColorBrush = new SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("Gold"));
            Setter setter = new Setter(Border.BackgroundProperty, Brushes.Blue, "Border");
            Style style = new Style(typeof(Border));
            style.Setters.Add(setter);
        
            this.myPage1.Resources = new ResourceDictionary();
            this.myPage1.Resources.Add("MyBrush", solidColorBrush);
            this.myPage1.Resources.Add("PageBackground", style);

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

the_king

مدیرکل انجمن
:green:
خیلی ممنون استاد .
کلا هر کلاس ، در اعضای استاتیکش ، برای پروپرتی هاش ، فیلدی بنام PropertyName+Property داره ، که شی DependencyProperty را برمیگردونه؟
هر که نه، طراحش اگه لازم دیده چیزی توسط Setter قابل ست کردن باشه یک همچین چیزی لازم داشته، سبک مایکروسافت هم اینطوری بوده که یک فیلد با این شیوه نامگذاری اضافه کنه.
این کلاس DependencyProperty ، کار همون کلاس PropertyInfo را نمیکنه؟
شبیه که چرا هست، اما یک سری تفاوت اساسی داره، PropertyInfo بر اساس یک ساختار خاص مقدار صریح میده، اطلاعاتش دقیقا در مورد یک کلاس با ساختار ثابت ئه، به اصطلاح owner اش عوض نمیشه. فرضا اگه برای Border هست فقط برای Border ئه، و باید از قبل هم بوده باشه تا همچین مشخصاتی رو بده. اما DependencyProperty صرفا آدرس کلی میده، اونم نه فقط برای یک مورد خاص، Owner اش ممکنه چند جور کلاس مختلف باشه، برای همین متد AddOwner داره. یعنی لازم نیست این Background که Brush ئه حتما برای یک Border باشه، آدرس کلی میده که بدرد هر Background ای که Brush باشه میخوره. برای چیزی که ممکنه قبل از این نبوده باشه هم ثبت شدنیه.

پس با این اوضاع ، معادل کد سی شارپِ اون کد xml ، کد زیر میشه؟ (درباره ی اون Brushes.Blue هم خیلی ممنون) :

کد:
            SolidColorBrush solidColorBrush = new SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("Gold"));
            Setter setter = new Setter(Border.BackgroundProperty, Brushes.Blue, "Border");
            Style style = new Style(typeof(Border));
            style.Setters.Add(setter);
       
            this.myPage1.Resources = new ResourceDictionary();
            this.myPage1.Resources.Add("MyBrush", solidColorBrush);
            this.myPage1.Resources.Add("PageBackground", style);

خیلی ممنون استاد :rose:
نزدیک ئه اما یک تفاوت و اشکال در تعریف Setter تون هست که استفاده ازش رو دچار مشکل میکنه. اون targetName که بهش "Border" رو دادید نوع داده که نیست، اسم گره فرزند ئه. برای این بکار میره که بگن این Setter فقط روی فرزندی اعمال بشه که اسمش فلان ئه. در XML برای Setter هیچ صفت TargetName ای مشخص نشده که شما اینجا نامی مثل "Border" برایش مشخص کنید. یا اصلا متد سازنده دیگری از Setter رو بکار ببرید تا اون پارامتر رو مشخص نکنید یا بهش مقدار null بدهید.
 

SajjadKhati

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

کد:
        <Page.Resources>
            <SolidColorBrush x:Key="MyBrush" Color="Gold"/>
            <Style TargetType="Border" x:Key="PageBackground">
                <Style.Setters>
                    <Setter Property="Background" Value="Blue"/>
                </Style.Setters>
            </Style>
        </Page.Resources>

بعد اینکه استاد ، در کد بالا ، وقتی درون تگ Style (اونجایی که تگ Style را باز کردیم و هنوز نبستیم . یعنی در کنار پروپرتی TargetType و ...) ، مینویسم Setter ، این عضو Setter را اصلا در لیست پروپرتی ها در اینتلیسنس نمیاوره . دلیل این نیاوردن در لیست ، چیه؟
تا اینکه به عنوان تگِ فرزندِ Style ، تگِ Style.Setters را نوشتم (در کد بالا میبینید) و به این ترتیب دیگه مشکلی نبود و در لیست اعضای اینتلیسنس آورد .

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

یه چیز دیگه اینکه الان در کد زیر :

کد:
        <Button Width="300" Height="100" Margin="10, 10" HorizontalAlignment="Left" VerticalAlignment="Top">
            <Button.Content>
                <Button Content="Child Button" Background="LightSteelBlue" FontSize="20" Height="100"  HorizontalAlignment="Left" VerticalAlignment="Top">
                    <Button.Width>
                        -----------------------------------------------------
                    </Button.Width>
                </Button>
            </Button.Content>
        </Button>

در جایی که خط چین کشیده شد (در محتوای تگ Button.Width که همون دکمه ی Child Button هست) ، اگه من بخوام به هر دلیلی ، در این قسمت ، به اطلاعات و اعضای دکمه ی والدش دسترسی داشته باشم ، چی کار باید کنم؟
اگه من در اون قسمت خط چین تگی باز کنم و توش بنویسم Button ، فقط به شی آخری ، یعنی به شی Child Button دسترسی خواهد داشت . اما من اگه در اون قسمت بخوام یه پروپرتی از اعضای Button ده والدش را ست کنم یا get کنم، چی کار باید کنم؟

نزدیک ئه اما یک تفاوت و اشکال در تعریف Setter تون هست که استفاده ازش رو دچار مشکل میکنه. اون targetName که بهش "Border" رو دادید نوع داده که نیست، اسم گره فرزند ئه. برای این بکار میره که بگن این Setter فقط روی فرزندی اعمال بشه که اسمش فلان ئه. در XML برای Setter هیچ صفت TargetName ای مشخص نشده که شما اینجا نامی مثل "Border" برایش مشخص کنید. یا اصلا متد سازنده دیگری از Setter رو بکار ببرید تا اون پارامتر رو مشخص نکنید یا بهش مقدار null بدهید.

خیلی ممنون استاد . پس کد سی شارپ اش این میشه؟ :

کد:
            SolidColorBrush solidColorBrush = Brushes.Gold;
            Setter setter = new Setter(Border.BackgroundProperty, Brushes.Blue);
            Style style = new Style(typeof(Border));
            style.Setters.Add(setter);

            this.myPage1.Resources = new ResourceDictionary();
            this.myPage1.Resources.Add("MyBrush", solidColorBrush);
            this.myPage1.Resources.Add("PageBackground", style);

درباره ی جواب بقیه ی قسمت هاتون هم ممنون :rose:
 

the_king

مدیرکل انجمن
استاد ، اون کد xml ، بصورت دقیق تر ، کد زیر میشه دیگه . درسته؟ (منظورم از دقیق تر اینه که بصورت explicit خودمون همه چیز را بنویسیم . مثل کلمه ی کلیدی this که در سی شارپ که کمپایلر گاها نمیذاره) :

کد:
        <Page.Resources>
            <SolidColorBrush x:Key="MyBrush" Color="Gold"/>
            <Style TargetType="Border" x:Key="PageBackground">
                <Style.Setters>
                    <Setter Property="Background" Value="Blue"/>
                </Style.Setters>
            </Style>
        </Page.Resources>
نه. در XML چیزی خلاصه شده چیز دیگه ای نیست. متنی می نویسید که به چیزی تفسیر بشه. برای یک مفهوم نگارش های مختلفی همون تفسیر رو میده، هیچکدوم دقیق تر، کاملتر یا صریح تر از نگارش های دیگه نیستند. می توانید یکسری تگ ها رو به شکل های مختلفی بنویسید یا بین علائم کاراکتر های فاصله و سطر های خالی اضافه کنید یا همه رو یک سطر کنید، المنت های تو در تو رو با فاصله تراز کنید یا نکنید. با همه اینکار ها شکل نگارش شون عوض میشه ولی خلاصه تر یا کامل تر نمیشه. همانطور که 100 و 0000100+ و 0x64 و 0b1100100 هیچکدوم کاملتر یا خلاصه تر یا صریح تر از اون یکی نیستند.

بعد اینکه استاد ، در کد بالا ، وقتی درون تگ Style (اونجایی که تگ Style را باز کردیم و هنوز نبستیم . یعنی در کنار پروپرتی TargetType و ...) ، مینویسم Setter ، این عضو Setter را اصلا در لیست پروپرتی ها در اینتلیسنس نمیاوره . دلیل این نیاوردن در لیست ، چیه؟
چون میدونه اونجا همچین چیزی رو نمی توانید بکار ببرید. Style چیزی به عنوان Setter نداره، Setters داره که اونم مجموعه است، Collection ئه، شما چه مقداری می خواهید در "..."=Setters بنویسید که فرمت قابل قبولی داشته باشه؟ چون میدونه همچین کاری نمی توانید بکنید دلیلی نمی بینه که بهتون پیشنهادش کنه.

یه چیز دیگه اینکه الان در کد زیر :

کد:
        <Button Width="300" Height="100" Margin="10, 10" HorizontalAlignment="Left" VerticalAlignment="Top">
            <Button.Content>
                <Button Content="Child Button" Background="LightSteelBlue" FontSize="20" Height="100"  HorizontalAlignment="Left" VerticalAlignment="Top">
                    <Button.Width>
                        -----------------------------------------------------
                    </Button.Width>
                </Button>
            </Button.Content>
        </Button>


در جایی که خط چین کشیده شد (در محتوای تگ Button.Width که همون دکمه ی Child Button هست) ، اگه من بخوام به هر دلیلی ، در این قسمت ، به اطلاعات و اعضای دکمه ی والدش دسترسی داشته باشم ، چی کار باید کنم؟
اگه من در اون قسمت خط چین تگی باز کنم و توش بنویسم Button ، فقط به شی آخری ، یعنی به شی Child Button دسترسی خواهد داشت . اما من اگه در اون قسمت بخوام یه پروپرتی از اعضای Button ده والدش را ست کنم یا get کنم، چی کار باید کنم؟
معنی نمیده، شما در XML قراره چیزی رو توصیف کنید، هر چیزی در جای مربوط به خودش توصیف می کنید. اگر چیزی رو در جای خودش توصیف نکردید یعنی جزو توصیف هاش نبوده. جای دیگری به اون ربطی نداره و نمیتوانید بگید من فلان چیز یادم رفت اینجا بگم. اگر میخواهید شماره پلاک منزل رو مشخص کنید اینکار رو هنگام توصیف لباس در کمد داخل اتاق تان که نمی کنید. کد XML هم کد زبان برنامه نویسی مفسری نیست که بگید ببینه در فلان جا فلان مشخصه فلان شیء چه مقداری داره. در XML ویژگی Binding هست که در مثالهایش هم می توانید ببینید، ولی اون در زمان اجرای برنامه کاری انجام میده، نه بررسی اجزاء ویژوال خود XML ای که داره توصیف میشه. در HTML وقتی میخوان یک کد اجرایی بنویسند که چیزی رو تفسیر کنه یا به فلان جزء اشاره کنه با HTML خالی نمی توانند، از javascript استفاده می کنند، XAML مثل همون HTML بدون javascript ئه.

خیلی ممنون استاد . پس کد سی شارپ اش این میشه؟ :

کد:
            SolidColorBrush solidColorBrush = Brushes.Gold;
            Setter setter = new Setter(Border.BackgroundProperty, Brushes.Blue);
            Style style = new Style(typeof(Border));
            style.Setters.Add(setter);

            this.myPage1.Resources = new ResourceDictionary();
            this.myPage1.Resources.Add("MyBrush", solidColorBrush);
            this.myPage1.Resources.Add("PageBackground", style);

درباره ی جواب بقیه ی قسمت هاتون هم ممنون :rose:
بله.
 

SajjadKhati

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

کد:
<ControlTemplate x:Key="roundbutton" TargetType="Button">
    <Grid>
        <Ellipse Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" />
        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Grid>
</ControlTemplate>

که در صفحه ی زیر هست :
Create a template in WPF - .NET Desktop - WPF

اولا هر وقت علامت {} اومد ، همون Markup extensions هستند و Markup extensions هم یعنی قرار نیست مقدار لیترال ای که تا حالا میدادیم ، بدیم و باید مقدارش را از جای دیگه و از متغییری (یا گاها key ای) که قبلا در جای دیگه تعریف شده یا کلا قراره تعریف بشه ، بگیره . درسته؟

دوما TemplateBinding ، دو تا پروپرتی را به هم پیوند میده . یعنی مقدار یه پروپرتی را توی یه پروپرتی دیگه میریزه . یا به عبارتی در کد Fill="{TemplateBinding Background} در بالا ، مقدار پروپرتیِ Background را در پروپرتیِ Fill میریزه . درسته؟

سوما چون TargetType ، از نوع Button ، یعنی شیِ button ای که قرار هست از این ControlTemplate استفاده کنه ، پروپرتی Background و Foreground ، مربوط به اون شیِ button خواهند بود . به عبارتی دیگه ، بعد از عبارت TemplateBinding ، نام پروپرتی ای را که میاریم ، اون پروپرتی ، همون پروپرتیِ مربوط به TargetType ای هست که در ControlTemplate مشخص کرده بودیم . و بنابراین مقدارش را از اون کنترل (در اینجا کنترل button) میگیره .
بنابراین مقدار Background از کنترل و شی button (ای که بعدا از این ControlTemplate استفاده میکنه) ، توی پروپرتیِ Fill از شیِ Ellipse در کد بالا ریخته میشه .
درسته؟

چهارما وقتی button ای از این ControlTemplate استفاده کنه (کد بالا) ، اولا داخل content مربوط به اون دکمه ، یه کنترل grid رسم میشه که باز داخل اون grid به عنوان content ، شی (کنترل) ellipse و ContentPresenter رسم میشه .
درسته؟
ContentPresenter برای حالت دادن استفاده میشه؟
 
آخرین ویرایش:

the_king

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

کد:
<ControlTemplate x:Key="roundbutton" TargetType="Button">
    <Grid>
        <Ellipse Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" />
        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Grid>
</ControlTemplate>

که در صفحه ی زیر هست :
Create a template in WPF - .NET Desktop - WPF

اولا هر وقت علامت {} اومد ، همون Markup extensions هستند و Markup extensions هم یعنی قرار نیست مقدار لیترال ای که تا حالا میدادیم ، بدیم و باید مقدارش را از جای دیگه و از متغییری (یا گاها key ای) که قبلا در جای دیگه تعریف شده یا کلا قراره تعریف بشه ، بگیره . درسته؟
بله. دست تون باز نیست که هر چیزی در اونجا بنویسید، نمی توانید بنویسید "{1+1}"= که موقع اجرا بشه 2 . محدود به مواردی هستید که برای اون قسمت تعریف شده.

دوما TemplateBinding ، دو تا پروپرتی را به هم پیوند میده . یعنی مقدار یه پروپرتی را توی یه پروپرتی دیگه میریزه . یا به عبارتی در کد Fill="{TemplateBinding Background} در بالا ، مقدار پروپرتیِ Background را در پروپرتیِ Fill میریزه . درسته؟
نه، Binding ئه، با اینکه بنویسید x = y فرق داره. احتمالا در Windows Forms هم با Binding کار نکردید. وقتی x رو Bind می کنید به y، هر زمان y تغییر کرد x هم عوض میشه، یعنی اگه شما بعد Bind کردن مقدار Foreground اون Button رو عوض کنید مقدار مشخصه Stroke در اون Ellipse هم عوض میشه. اون TemplateBinding برای این نیست که الان مقدار فلان رو بده به بهمان و دیگه بعدا کاری بهش نداشته باشه. Binding مقدار چیزی رو وابسته میکنه به تغییرات چیز دیگری.

سوما چون TargetType ، از نوع Button ، یعنی شیِ button ای که قرار هست از این ControlTemplate استفاده کنه ، پروپرتی Background و Foreground ، مربوط به اون شیِ button خواهند بود . به عبارتی دیگه ، بعد از عبارت TemplateBinding ، نام پروپرتی ای را که میاریم ، اون پروپرتی ، همون پروپرتیِ مربوط به TargetType ای هست که در ControlTemplate مشخص کرده بودیم . و بنابراین مقدارش را از اون کنترل (در اینجا کنترل button) میگیره .
بنابراین مقدار Background از کنترل و شی button (ای که بعدا از این ControlTemplate استفاده میکنه) ، توی پروپرتیِ Fill از شیِ Ellipse در کد بالا ریخته میشه .
درسته؟
بله.

چهارما وقتی button ای از این ControlTemplate استفاده کنه (کد بالا) ، اولا داخل content مربوط به اون دکمه ، یه کنترل grid رسم میشه که باز داخل اون grid به عنوان content ، شی (کنترل) ellipse و ContentPresenter رسم میشه .
درسته؟
نه. Content اون دکمه تغییری نمی کنه، همون string ئه Button 2 میمونه. شما حتی اگر بعدا در حالی که اون ControlTemplate داره نمایش داده میشه Content اون دکمه رو با یک متن یا حتی یک المنت دیگه پر کنید همچنان اون Ellipse سرجاش داره نمایش داده میشه. زیبا است، نه؟ :)
ContentPresenter برای حالت دادن استفاده میشه؟
بله ولی از اون مهمتر، مشخص میکنه که در این ترکیب ظاهری جای Content کجا است، اگه مشخص اش نکنید ControlTemplate جایی برای نمایش اون Button نداره.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بله. دست تون باز نیست که هر چیزی در اونجا بنویسید، نمی توانید بنویسید "{1+1}"= که موقع اجرا بشه 2 . محدود به مواردی هستید که برای اون قسمت تعریف شده.

سلامی مجدد
خیلی ممنون استاد . :rose:
آره میدونم . باید طبق قوانین و چیزهایی که در markup extention مربوط به اون دستور گفته (مثلا دستور StaticResource و یا هر دستور دیگه) ، عمل کنیم .
راستی استاد ، تفاوت StaticResource و DynamicResource چیه؟
من دیدم که بیشتر اوقات از دستور StaticResource استفاده میشه .
تفاوت شون هم فقط موقع فراخونی این دستورات هست دیگه؟ درسته؟ یعنی مثلا وقتی میخوایم توی Resource مربوط به کنترلی ، دیکشنری و کلا اشیاهایی تعریف کنیم ، خودمون تعریف میکنیم . یعنی موقع تعریف کردن ، مشخص نمیشه که Resource مون Static هست یا Dynamic . درسته؟ تفاوت ، فقط موقع فراخونی و استفاده از این Resource های تعریف شده هست که بصورت StaticResource یا DynamicResource بخوایم اونها را فراخونی کنیم . درسته؟

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

بعد اینکه استاد ، من قشنگ این قضیه ی فضای نام ها را درک نکردم . الان این فضای نام هایی که با xlmns تعریف میشن ، در واقع برابر با همونی هستند که در سی شارپ ، از using استفاده میکردیم؟ (مثلا using System.Windows) ؟
و این مقادیر url ای که برای این فضای نام در نظر گرفته شد ، آیاد در مفسر xml در wpf ، مثلا تعریف شد که برای هر کدوم از این فضای نام (مثلا برای فضای نام با پیشوند x) ، یه مجموعه ای از فضای نام ها در دات نت استفاده بشه؟ یعنی وقتی مثلا فضای نام x (در xml) فراخونی شد ، این فضای نام ، دربرگیرنده ی مجموعه ای از فضای نام ها در دات نت (مثلا System.Windows و System.Windows.Controls و ...) میشه؟ و به این ترتیب هست که میشه در xml از فضای نام های دات نت و بنابراین از کلاس های دات نت ، استفاده کرد؟

اگه این طور هه ، مثلا بیاد یه کنترل یا کلا یه فضای نام ای از دات نت را بخوایم استفاده کنیم که در فضای نام های xml اش وجود نداره . در این صورت باید چجوری فضای نام دات نت را به xml اضافه کنیم (تا بتونیم از اون کنترل یا کلاس استفاده کنیم)؟
اگه این طور نیست ، پس من دقیق رابطه ی فضای نام xml و فضای نام دات نت را متوجه نشدم . یعنی متوجه نشدم که چجوری میشه که با استفاده از فضای نام پیش فرض xml (که بدون پیشوند هست) ، وقتی تگ Button را مینویسیم ، میدونه منظورمون اسمبلی PresentationFramework.dll و فضای نام System.Windows.Controls و کلاس Button هست؟

نه، Binding ئه، با اینکه بنویسید x = y فرق داره. احتمالا در Windows Forms هم با Binding کار نکردید. وقتی x رو Bind می کنید به y، هر زمان y تغییر کرد x هم عوض میشه، یعنی اگه شما بعد Bind کردن مقدار Foreground اون Button رو عوض کنید مقدار مشخصه Stroke در اون Ellipse هم عوض میشه. اون TemplateBinding برای این نیست که الان مقدار فلان رو بده به بهمان و دیگه بعدا کاری بهش نداشته باشه. Binding مقدار چیزی رو وابسته میکنه به تغییرات چیز دیگری.

کار که قبلا بصورت سطحی (شاید هم فقط در حد تئوری و نه عملی) کار کردم ولی نه چندان .
پس اولا پروپرتیِ Background از Button را توی پروپرتیِ Fill از شی Ellipse میریزه و هر وقت اگه مقدار پروپرتیِ Background از Button ، تغییر کنه ، مقدارپروپرتیِ Fill از شی Ellipse هم (به همون مقدار) ،تغییر میکنه . درسته؟

نه. Content اون دکمه تغییری نمی کنه، همون string ئه Button 2 میمونه. شما حتی اگر بعدا در حالی که اون ControlTemplate داره نمایش داده میشه Content اون دکمه رو با یک متن یا حتی یک المنت دیگه پر کنید همچنان اون Ellipse سرجاش داره نمایش داده میشه. زیبا است، نه؟ :)
بله ولی از اون مهمتر، مشخص میکنه که در این ترکیب ظاهری جای Content کجا است، اگه مشخص اش نکنید ControlTemplate جایی برای نمایش اون Button نداره.

بله قشنگ هه :)
الان استاد ، من از Control Template این جوری متوجه شدم . ببینین درسته؟ :
خود (شیِ کلاسِ) ControlTemplate ، انگار چیز خاصی نیست . توش میتونیم مشخص کنیم که چه رسم هایی میشه توی کنترل مورد نظر ، انجام بدیم . اولا مثل قضیه ی Style ها ، باید TargetType اش را مشخص کنیم .
دوما 2 عنوان کلی را باید توش رسم یا مدیریت کنیم . اولی ، شکل دلخواه مون هست (که با هر کلاسی مثل Ellipse و ... میتونیم رسم کنیم) که بجای شکلِ رایجِ اون TargetType مون که مشخص کرده بودیم ، رسم میشه و دومی ، محتوا (یا پروپرتیِ Content) مربوط به اون TargetType مون که مشخص کرده بودیم را باید با کلاس ContentPresenter ، مدیریت و رسم و تراز اش را تنظیم کنیم .
درسته؟

پس با رسم مثلا Ellipse مون ، کلا رسم دکمه ، انجام نمیشه و بجاش رسم Ellipse مون جایگزین اش میشه دیگه . درسته؟
پس شبیه OnPaint در win form عمل میکنه . یعنی رسم اون کنترل را کلا نادیده میگیره و بجاش کاربر میتونه رسم دلخواهش را اون هم از ابتدا رسم کنه . درسته؟

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

خوب حالا سئوال مهم اینها هستند :

1) چجوری میتونیم توی یه کنترل ، توسط Template ها ، برای یه کنترل که برای یه قسمت ، پروپرتی ای در نظر نگرفت را بهش پروپرتی داد؟
مثلا در کنترل CheckBox ، پروپرتی ای در نظر گرفته نشد که بتونیم رنگ پشت زمینه ی قسمت Content (اگه Content مون ، متن ساده باشه) را عوض کنیم .
اگه بخوایم این یه CheckBox شخصی برای خودمون در نظر بگیریم که این قابلیت را داشته باشه ، اول باید در ControlTemplate ، یک Grid رسم کنیم (به عنوان parent یا والد) . بعد داخلش یه کنترل دلخواه (مثلا یه Grid دیگه) رسم کنیم و لوکیشنِ این گرید جدید را جوری تنظیم کنیک که در پشت متن (context مربوط به CheckBox) بیفته (یا کلا در جایی که خودمون در نظر داریم) و بعد در Grid ئه والد ، یه CheckBox هم رسم کنیم که مشخصاتش را از CheckBox ای که در TargetType ئه مربوط به ControlTemplate مشخص کرده بودیم ، بگیره .
درسته؟ (کلا متوجه ی منظورم از این قسمتِ 1 شدین؟)


2) حالا اگه بخوایم یه قسمتی از یه کنترل را تغییر بدیم که استایل اش فرق کنه (منظورم از استایل ، پروپرتیِ Style نیست) . یعنی شکل اون بخش ، یه کم متفاوت باشه . یا رنگش متفاوت باشه . مثلا قسمتی که در چک باکس ، علامت و شکلِ "تیک" رسم میشه ، شکل "تیک" استایل اش فرق کنه . مثلا نوکِ رسمِ شکلِ "تیک" ، یه کم تیزتر باشه یا رنگ "تیک" فرق کنه . مثلا مثل شکل زیر که CheckBox در تنظیمات PowerDVD هست ، باشه :

1 checkbox.JPG

اگه همچین شکلی بخوایم ، باید چی کار کنیم؟
اگه اون بخش "تیک" را بخوایم رنگش را هم تغییر بدیم ، چی؟
کلا راهکارش اینه که باید اون بخشِ "تیک" را خودمون توسط اشکالی که در دات نت و wpf هست ، از اول رسم کنیم یا نه؟
اگه اشتباه نکنم ، یه کلاس های Decorator (مثل BulletDecorator) برای این کارها تعبیه شدند. درسته؟
یعنی تعبیه شدند تا کارها و رسم هایی که براشون پروپرتی در نظر گرفته نشدند را انجام داد . درسته؟ حالا من دقیق این کلاس را نمیشناسم . چون تازه توی چند تا کد دیدم . این کلاس دقیقا برای چه کاری استفاده میشه؟
چون این کلاس خیلی عضو داره ، 4 تا 5 تا از مهمترین عضوهاشون را نام میبرین تا بررسی کنم؟
مثلا به عضو Bullet در این کلاس ، میتونیم کنترل بدیم . عضو مهم دیگه هم Child هست که این هم کنترل دریافت میکنه و با Bullet تراز میشه . (اگه درست گفته باشم) . کلا یه کم درباره ی این کلاس و کلا کلاس هایی که موقع رسم و زمان شخصی سازی کنترل ها کاربرد دارند را میگین؟

منظورم این نیست کد بدین .منظورم اینه که راهکارِ کلی برای رسیدن به این هدف (و یا در صورت نیاز ، کلاس هایی که برای این کار) لازم هست را اگه معرفی کنین ، ممنون میشم .


3) یا اگه ComboBox ای بخوایم شبیه اونچه که در تنظیمات PowerDVD هست ، رسم کنیم ، چطور؟ :

2 combobox.JPG

یعنی کلا بتونیم رنگ همه ی قسمت هاش را در نظر بگیریم و مدیریت کنیم ، چی کار باید کرد؟ (راهکار کلی اش منظورم هست) .
در ComboBox ، مقدار رنگ در پروپرتی Background و BorderBrush را عوض میکنم (بصورت بصری در پنجره ی Properties . نه بصورت کد نویسی) ، هیچ قسمت از رنگ هاش تغییر پیدا نمیکنه . چرا؟!


4) در کنترل های wpf ، یه کنترلی هست که شبیه RadPageView (که در کمپوننت های تلریک هست) باشه؟
چون RadPageView را میشه تقریبا همه ی قسمت هاش را تغییر داد و خوشکل اش کرد .
RadPageView هم شبیه TabControl در wpf هست اما خیلی خوشکل تر هه . جوری که اگه بخوایم TabControl را شبیه اون کنیم ، فکر کنم از اساس باید تغییرش بدیم .

خیلی زیاد شد . ببخشید :)
خیلی ممنون استاد :rose:
 
آخرین ویرایش:

the_king

مدیرکل انجمن
سلامی مجدد
خیلی ممنون استاد . :rose:
آره میدونم . باید طبق قوانین و چیزهایی که در markup extention مربوط به اون دستور گفته (مثلا دستور StaticResource و یا هر دستور دیگه) ، عمل کنیم .
راستی استاد ، تفاوت StaticResource و DynamicResource چیه؟
من دیدم که بیشتر اوقات از دستور StaticResource استفاده میشه .
تفاوت شون هم فقط موقع فراخونی این دستورات هست دیگه؟ درسته؟ یعنی مثلا وقتی میخوایم توی Resource مربوط به کنترلی ، دیکشنری و کلا اشیاهایی تعریف کنیم ، خودمون تعریف میکنیم . یعنی موقع تعریف کردن ، مشخص نمیشه که Resource مون Static هست یا Dynamic . درسته؟ تفاوت ، فقط موقع فراخونی و استفاده از این Resource های تعریف شده هست که بصورت StaticResource یا DynamicResource بخوایم اونها را فراخونی کنیم . درسته؟
StaticResource رو برای داده ای بکار می برید که همون موقع فراخوانی XAML مقدارش در دسترس ئه و بعدا هم قرار نیست مقدارش تغییری بکنه. پویا نیست که انتظار تغییری داشته باشیم.
همچین داده ای همون موقع که {StaticResource} بکار برده میشه داده اش رو میخونه و تمام. اگر بعدا مقدار اون مدخل Resources رو هم عوض کنید، چون قبلا فراخوانی برای StaticResource انجام شده بوده این تغییر مقدار روی {StaticResourc} های مربوط به اون کلید تاثیری نداره.
اما DynamicResource رو برای داده ای بکار می برید که الزاما ثابت نمیمونه. فرضا اگه DynamicResource رو برای مقدار دهی مشخصه فلان بکار ببرین، هر بار که مقدار اون مدخل رو تغییر بدید مقدار اون مشخصه هم تغییر میکنه، یعنی میدونه که این منبع داده پویا است و صرفا به فراخوانی موقع فراخوانی XAML بسنده نمیشه.

بعد اینکه استاد ، من قشنگ این قضیه ی فضای نام ها را درک نکردم . الان این فضای نام هایی که با xlmns تعریف میشن ، در واقع برابر با همونی هستند که در سی شارپ ، از using استفاده میکردیم؟ (مثلا using System.Windows) ؟
و این مقادیر url ای که برای این فضای نام در نظر گرفته شد ، آیاد در مفسر xml در wpf ، مثلا تعریف شد که برای هر کدوم از این فضای نام (مثلا برای فضای نام با پیشوند x) ، یه مجموعه ای از فضای نام ها در دات نت استفاده بشه؟ یعنی وقتی مثلا فضای نام x (در xml) فراخونی شد ، این فضای نام ، دربرگیرنده ی مجموعه ای از فضای نام ها در دات نت (مثلا System.Windows و System.Windows.Controls و ...) میشه؟ و به این ترتیب هست که میشه در xml از فضای نام های دات نت و بنابراین از کلاس های دات نت ، استفاده کرد؟
نه. مطالب قبلی رو دوباره مرور کنید. صرفا یک متن ئه، درسته که متن یک لینک URI ئه ولی فراخوانی یا چیزی شبیه به این نمیشه. طبع تعریف XML فضای نام باید با قالب URI باشه، مثل لینک صفحات وب، ولی قرار نیست حتما در اون URI محتوای خاصی در دسترس باشه، حتی ممکنه اصلا اون URI در اینترنت وجود نداشته باشه.

اگه این طور هه ، مثلا بیاد یه کنترل یا کلا یه فضای نام ای از دات نت را بخوایم استفاده کنیم که در فضای نام های xml اش وجود نداره . در این صورت باید چجوری فضای نام دات نت را به xml اضافه کنیم (تا بتونیم از اون کنترل یا کلاس استفاده کنیم)؟
اگه این طور نیست ، پس من دقیق رابطه ی فضای نام xml و فضای نام دات نت را متوجه نشدم . یعنی متوجه نشدم که چجوری میشه که با استفاده از فضای نام پیش فرض xml (که بدون پیشوند هست) ، وقتی تگ Button را مینویسیم ، میدونه منظورمون اسمبلی PresentationFramework.dll و فضای نام System.Windows.Controls و کلاس Button هست؟
WPF و XAML نحوه فراخوانی و اجراش مشخصه و ثابت. کتابخانه های اساسی مورد استفاده اش از قبل مشخص شدن. شما دو تا چیز نامرتبط رو میخواهید بزور ربط بدید بهم.
چرا باید حتما رابطه ای بین XML و فضای نام در NET. باشه که حالا دنبال درک این رابطه باشید؟

پس اولا پروپرتیِ Background از Button را توی پروپرتیِ Fill از شی Ellipse میریزه و هر وقت اگه مقدار پروپرتیِ Background از Button ، تغییر کنه ، مقدارپروپرتیِ Fill از شی Ellipse هم (به همون مقدار) ،تغییر میکنه . درسته؟
بله.

الان استاد ، من از Control Template این جوری متوجه شدم . ببینین درسته؟ :
خود (شیِ کلاسِ) ControlTemplate ، انگار چیز خاصی نیست . توش میتونیم مشخص کنیم که چه رسم هایی میشه توی کنترل مورد نظر ، انجام بدیم . اولا مثل قضیه ی Style ها ، باید TargetType اش را مشخص کنیم .
دوما 2 عنوان کلی را باید توش رسم یا مدیریت کنیم . اولی ، شکل دلخواه مون هست (که با هر کلاسی مثل Ellipse و ... میتونیم رسم کنیم) که بجای شکلِ رایجِ اون TargetType مون که مشخص کرده بودیم ، رسم میشه و دومی ، محتوا (یا پروپرتیِ Content) مربوط به اون TargetType مون که مشخص کرده بودیم را باید با کلاس ContentPresenter ، مدیریت و رسم و تراز اش را تنظیم کنیم .
درسته؟
یک چیزی تو این مایه ها، ولی مثالی که میزنید به این معنا نیست که ControlTemplate همیشه فلان دو تا قسمت کلی رو داره. چون کلا تمرکز تون رو یکی دو مثال ساده بوده، تصور کاملی که از توانایی یا محتواش ندارید.

پس با رسم مثلا Ellipse مون ، کلا رسم دکمه ، انجام نمیشه و بجاش رسم Ellipse مون جایگزین اش میشه دیگه . درسته؟
پس شبیه OnPaint در win form عمل میکنه . یعنی رسم اون کنترل را کلا نادیده میگیره و بجاش کاربر میتونه رسم دلخواهش را اون هم از ابتدا رسم کنه . درسته؟
باز شروع کردید به فرضیه بافی. نه. بر اساس چه نتایجی دارید فرضیه طرح می کنید؟ اصلا اجراش رو دیدید که نتیجه گیری کنید؟
لااقل یکی دو مثال ازش بنویسید و اجرا کنید که بگید دیدم اجراش چطور بود و بعد برایش داستان بنویسید. مگه برای دکمه Template تعریف می کنید در اجرا رسم خود دکمه نادیده گرفته میشه؟

1) چجوری میتونیم توی یه کنترل ، توسط Template ها ، برای یه کنترل که برای یه قسمت ، پروپرتی ای در نظر نگرفت را بهش پروپرتی داد؟
مثلا در کنترل CheckBox ، پروپرتی ای در نظر گرفته نشد که بتونیم رنگ پشت زمینه ی قسمت Content (اگه Content مون ، متن ساده باشه) را عوض کنیم.
اگه بخوایم این یه CheckBox شخصی برای خودمون در نظر بگیریم که این قابلیت را داشته باشه ، اول باید در ControlTemplate ، یک Grid رسم کنیم (به عنوان parent یا والد) . بعد داخلش یه کنترل دلخواه (مثلا یه Grid دیگه) رسم کنیم و لوکیشنِ این گرید جدید را جوری تنظیم کنیک که در پشت متن (context مربوط به CheckBox) بیفته (یا کلا در جایی که خودمون در نظر داریم) و بعد در Grid ئه والد ، یه CheckBox هم رسم کنیم که مشخصاتش را از CheckBox ای که در TargetType ئه مربوط به ControlTemplate مشخص کرده بودیم ، بگیره .
درسته؟ (کلا متوجه ی منظورم از این قسمتِ 1 شدین؟)
دلیل اینکه CheckBox رنگ زمینه Content رو مشخص نمی کنه اینه که اصلا اون ناحیه رو رنگ نمی کنه. هر رنگی پشت اش باشه همونه. می توانید از ابتدا اون CheckBox رو داخل چیزی مثل Grid قرار بدید که Background دلخواه شما رو داشته باشه. وگرنه برای ساختن ControlTemplate باید به اجزاء اون توجه کنید، یکی دو خط نیست :
CheckBox Styles and Templates

2) حالا اگه بخوایم یه قسمتی از یه کنترل را تغییر بدیم که استایل اش فرق کنه (منظورم از استایل ، پروپرتیِ Style نیست) . یعنی شکل اون بخش ، یه کم متفاوت باشه . یا رنگش متفاوت باشه . مثلا قسمتی که در چک باکس ، علامت و شکلِ "تیک" رسم میشه ، شکل "تیک" استایل اش فرق کنه . مثلا نوکِ رسمِ شکلِ "تیک" ، یه کم تیزتر باشه یا رنگ "تیک" فرق کنه . مثلا مثل شکل زیر که CheckBox در تنظیمات PowerDVD هست ، باشه :

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

اگه همچین شکلی بخوایم ، باید چی کار کنیم؟
اگه اون بخش "تیک" را بخوایم رنگش را هم تغییر بدیم ، چی؟
کلا راهکارش اینه که باید اون بخشِ "تیک" را خودمون توسط اشکالی که در دات نت و wpf هست ، از اول رسم کنیم یا نه؟
اگه اشتباه نکنم ، یه کلاس های Decorator (مثل BulletDecorator) برای این کارها تعبیه شدند. درسته؟
یعنی تعبیه شدند تا کارها و رسم هایی که براشون پروپرتی در نظر گرفته نشدند را انجام داد . درسته؟ حالا من دقیق این کلاس را نمیشناسم . چون تازه توی چند تا کد دیدم . این کلاس دقیقا برای چه کاری استفاده میشه؟
چون این کلاس خیلی عضو داره ، 4 تا 5 تا از مهمترین عضوهاشون را نام میبرین تا بررسی کنم؟
مثلا به عضو Bullet در این کلاس ، میتونیم کنترل بدیم . عضو مهم دیگه هم Child هست که این هم کنترل دریافت میکنه و با Bullet تراز میشه . (اگه درست گفته باشم) . کلا یه کم درباره ی این کلاس و کلا کلاس هایی که موقع رسم و زمان شخصی سازی کنترل ها کاربرد دارند را میگین؟

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

3) یا اگه ComboBox ای بخوایم شبیه اونچه که در تنظیمات PowerDVD هست ، رسم کنیم ، چطور؟ :

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

یعنی کلا بتونیم رنگ همه ی قسمت هاش را در نظر بگیریم و مدیریت کنیم ، چی کار باید کرد؟ (راهکار کلی اش منظورم هست) .
به Style اش توجه کنید، از بخش های مختلفی تشکیل شده که هر کدوم هم مشخصات Template خودشون رو دارند.
ComboBox ControlTemplate Example

در ComboBox ، مقدار رنگ در پروپرتی Background و BorderBrush را عوض میکنم (بصورت بصری در پنجره ی Properties . نه بصورت کد نویسی) ، هیچ قسمت از رنگ هاش تغییر پیدا نمیکنه . چرا؟!
تغییر همه مشخصه ها منجر به بروز رسانی رسم نمیشه.
یا به این جور موارد عادت می کنید یا کلا میذارید WPF رو کنار. یک چیزی مثل IsEnabled اش رو تغییر بدید تا حالیش بشه که باید از نو رسم کنه.

4) در کنترل های wpf ، یه کنترلی هست که شبیه RadPageView (که در کمپوننت های تلریک هست) باشه؟
نمیدونم.
 

SajjadKhati

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

خیلی ممنون استاد .
بله . اجراش کردم دیگه . همون مثالی که در پست 73 دادم را اجرا کردم .
یعنی در کد :

کد:
<ControlTemplate x:Key="roundbutton" TargetType="Button">
    <Grid>
        <Ellipse Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" />
        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Grid>
</ControlTemplate>

وقتی کد بخش :

کد:
<Ellipse Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" MouseEnter="Ellipse_MouseEnter" MouseLeave="Ellipse_MouseLeave"/>

اش را حذف کنیم ، رسم دکمه (بجز بخش content اش) انجام نمیشه . و اون بخش بی رنگ میشه و پشت زمینه اش فقط مشخص میشه .

بعد اینکه در ControlTemplate ، هر کنترلی را که در بخش TargetType در ControlTemplate دادیم و اون کنترل ، از نوع ContentControl بود (از این کلاس ارث بری کرد) ، برای رسم محتوا اش (در واقع برای رسم هر چیزی که در پروپرتیِ Content اش بود) ، باید از ContentPresenter برای رسم محتواش استفاده کنیم .
درسته؟

در کد بالا ، وقتی بخش :
کد:
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />

را حذف کنیم ، رسم محتوای دکمه ، انجام نمیشه .

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

استاد ، در توضیحات بعضی از پروپرتی ها ، مثلا در توضیحات پروپرتی UIElement.IsMouseOver ، در خط آخرش نوشته :
"This is a dependency property."
این دقیقا یعنی چه و چه رابطه ای با اون قضیه ی کلاس DependencyProperty که قبلا در موردش بحث کردیم داره؟

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

استاد ، درباره ی اون قضیه ی "تیک" در checkbox که گفته بودم (شکلش را از نرم افزار powerdvd هم گذاشتم) ، این طور هم میشه که مثلا بخشِ "تیک" را در نرم افزار فتوشاپ رسم کنیم و مثلا در بخش resource مربوط به یک کنترل ، image ای در نظر بگیریم که عکس فایل png مربوط به این رسمی که در فتوشاپ انجام دادیم را بهش بدیم و بعد در ControlTemplate ، موقع تیک زدن (در Trigger اش) ، این image را اونجا رسم کنیم .
میشه دیگه . درسته؟

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

تغییر همه مشخصه ها منجر به بروز رسانی رسم نمیشه.
یا به این جور موارد عادت می کنید یا کلا میذارید WPF رو کنار. یک چیزی مثل IsEnabled اش رو تغییر بدید تا حالیش بشه که باید از نو رسم کنه.

مقدار IsEnabled و اینها را تغییر دادم ، باز هم رنگهای Background و اینها ، تغییر نکرد .

از جواب بقیه ی قسمت ها هم خیلی ممنون :rose:
 

the_king

مدیرکل انجمن
خیلی ممنون استاد .
بله . اجراش کردم دیگه . همون مثالی که در پست 73 دادم را اجرا کردم .
یعنی در کد :

کد:
<ControlTemplate x:Key="roundbutton" TargetType="Button">
    <Grid>
        <Ellipse Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" />
        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Grid>
</ControlTemplate>

وقتی کد بخش :

کد:
<Ellipse Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" MouseEnter="Ellipse_MouseEnter" MouseLeave="Ellipse_MouseLeave"/>

اش را حذف کنیم ، رسم دکمه (بجز بخش content اش) انجام نمیشه . و اون بخش بی رنگ میشه و پشت زمینه اش فقط مشخص میشه .
اتفاقی که می افته رو متوجه میشوم ولی نتیجه گیری ای که از این تغییر داشتید و به OnPaint ربطش دادید رو نه.
اگر با بوجود آوردن ControlTemplate رسم دکمه کلا نادیده گرفته میشه و انجام نمیشه، چطور شما با Background رسم زمینه دکمه رو می توانید توسط چیزی مثل Border انجام بدهید؟
مگه در OnPaint با رسم یک چیزی زمینه چیزی که رسم نشده و به قول شما نادیده گرفته شده رو میشه رسم کرد؟
کد:
        <ControlTemplate x:Key="MyButton" TargetType="Button">
            <Border Background="{TemplateBinding Background}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}">
                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
            </Border>
        </ControlTemplate>
اگر رسم نادیده گرفته میشه چطور میتونه رسم نادیده گرفته شده رو نه یکبار، بلکه دو بار رسم کنه؟
کد:
        <ControlTemplate x:Key="MyButton" TargetType="{x:Type Button}">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        Grid.Column="0">
                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                </Border>
                <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                        Grid.Column="1">
                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                </Border>
            </Grid>
        </ControlTemplate>

بعد اینکه در ControlTemplate ، هر کنترلی را که در بخش TargetType در ControlTemplate دادیم و اون کنترل ، از نوع ContentControl بود (از این کلاس ارث بری کرد) ، برای رسم محتوا اش (در واقع برای رسم هر چیزی که در پروپرتیِ Content اش بود) ، باید از ContentPresenter برای رسم محتواش استفاده کنیم .
درسته؟
بله.

در کد بالا ، وقتی بخش :
کد:
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
را حذف کنیم ، رسم محتوای دکمه ، انجام نمیشه .
بله. چون جایی رو برای رسم اش مشخص نکرده اید. شما ممکنه در یک ControlTemplate چند تا ContentPresenter با موقعیت های مختلف مکانی تعریف کنید، نه فقط یکی.
یعنی بگید اون Content رو در چند جا، مثلا اینجا و اونجا نشون بده.

استاد ، در توضیحات بعضی از پروپرتی ها ، مثلا در توضیحات پروپرتی UIElement.IsMouseOver ، در خط آخرش نوشته :
"This is a dependency property."
این دقیقا یعنی چه و چه رابطه ای با اون قضیه ی کلاس DependencyProperty که قبلا در موردش بحث کردیم داره؟
بله. یعنی از طریق یک DependencyProperty قابل دسترسی است و از تمامی قابلیت هایی که DependencyProperty ارائه میکنه تاثیر میگیره.
در توضیحات DependencyProperty هم که قابلیت هاش در بخش Remarks مشخص شده.

استاد ، درباره ی اون قضیه ی "تیک" در checkbox که گفته بودم (شکلش را از نرم افزار powerdvd هم گذاشتم) ، این طور هم میشه که مثلا بخشِ "تیک" را در نرم افزار فتوشاپ رسم کنیم و مثلا در بخش resource مربوط به یک کنترل ، image ای در نظر بگیریم که عکس فایل png مربوط به این رسمی که در فتوشاپ انجام دادیم را بهش بدیم و بعد در ControlTemplate ، موقع تیک زدن (در Trigger اش) ، این image را اونجا رسم کنیم .
میشه دیگه . درسته؟
مناسب نیست. رسم تصویر Bitmap در WPF با فلسفه اش جور در نمیاد، چون کلا بر پایه رسم برداری ئه و اون وسط رسم Bitmap که با افزایش ابعاد کیفیتش افزایش پیدا نمی کنه ناجور ئه.
اگر همچین قصدی رو دارید در مورد مثال های Panel.OnRender (و وارثین اش) و ImageBrush و ... مطالعه کنید، اما کلا رسم غیر برداری در WPF کار مناسبی نیست.

توی ویندوز فرم ، کلاس هایی وجود داشت که قسمت هایی از کنترل را بصورت آماده رسم میکرد . مثلا اگه یادتون باشه ، قبلا از یه کلاسی استفاده کردید که کنترل progressbar را رسم کردید (پشت زمینه ی کنترل progressbar منظورم هست . نه اینکه رنگ داخِ کنترل) . یادتون میاد؟ (اسم کلاسش فعلا یادم نیست) .
همچین کلاس های آماده ای برای رسم در wpf هست که بیاد بخشی از یه کنترل یا کل اش را رسم کنه؟
رسم در WPF بر اساس یکسری المنت ساده انجام میشه، یعنی یک تم گرافیکی خاصی مثل تم ویندوز نیست که یک تصویر از قبل ذخیره شده بیاد بشینه در فلان کادر و حالا شما برای دسترسی به تصویرش دنبال متد خاصی بگردید.
برای همینه که ابعاد WPF محدودیت نداره، فقط یکسری اجزاء ساده است که رنگ پیشفرض شون هم در مثال ها مشخص شده. می توانید Style و ControlTemplate کنترل ها رو ببینید و هر قسمتی که خواستید در ControlTemplate خودتون اضافه کنید.

مقدار IsEnabled و اینها را تغییر دادم ، باز هم رنگهای Background و اینها ، تغییر نکرد .
یک کاری رو درست انجام نمی دهید یا تنظیمی رو اعمال می کنید یا از قلم می اندازید که بخاطرش نادیده گرفته میشه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
اتفاقی که می افته رو متوجه میشوم ولی نتیجه گیری ای که از این تغییر داشتید و به OnPaint ربطش دادید رو نه.
اگر با بوجود آوردن ControlTemplate رسم دکمه کلا نادیده گرفته میشه و انجام نمیشه، چطور شما با Background رسم زمینه دکمه رو می توانید توسط چیزی مثل Border انجام بدهید؟
مگه در OnPaint با رسم یک چیزی زمینه چیزی که رسم نشده و به قول شما نادیده گرفته شده رو میشه رسم کرد؟
کد:
        <ControlTemplate x:Key="MyButton" TargetType="Button">
            <Border Background="{TemplateBinding Background}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}">
                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
            </Border>
        </ControlTemplate>
اگر رسم نادیده گرفته میشه چطور میتونه رسم نادیده گرفته شده رو نه یکبار، بلکه دو بار رسم کنه؟
کد:
        <ControlTemplate x:Key="MyButton" TargetType="{x:Type Button}">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        Grid.Column="0">
                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                </Border>
                <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                        Grid.Column="1">
                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                </Border>
            </Grid>
        </ControlTemplate>

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

استاد ، احتمالا من دقیق منظورم را نرسوندم .
کدهاتون مشخص هه دیگه . اگه Border را نذارید یا در Grid ، رسم ای انجام ندید (مثلا در Background اش) ، مشخص هست که رسم ای در Button تون انجام نمیشه . حالا که Border گذاشتید و پروپرتی هاش را ست کردین ، مشخص هست که رسم در Button انجام میشه دیگه . Border در کدتون ، کارِ Ellipse در کدی که از اون صفحه دادم را انجام میده .
منظورم این بود که در کل شبیه OnPaint هست . نه دقیقا .
اینکه ContentPresenter را در قسمت Content در شی Border گذاشتید ، برام جالب بود .

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

کاری نمیکنم .
فقط از toolbox یه شی combobox میذارم توی صفحه و background و borderbrush اش را تغییر میدم . اما رنگ شون تغییر نمیکنه . همین .
درباره جواب بقیه ی قسمت ها هم خیلی ممنون :rose:

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

و اینکه استاد در لینک زیر :

Create a template in WPF - .NET Desktop - WPF

در کد زیر که در صفحه ی بالا گفت :

کد:
<ControlTemplate x:Key="roundbutton" TargetType="Button">
    <Grid>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup Name="CommonStates">
                <VisualState Name="Normal">
                </VisualState>
                <VisualState Name="MouseOver">
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Grid>
</ControlTemplate>

(من کد بالا را 2 خط آخرش که به سئوالم مربوط نمیشد را حذف کردم) .
الان وقتی داخل محتوا و content (منظورم content در xml هست . نه پروپرتیِ content) در Grid ، چیزی مینویسیم و تگ ای میذاریم (تگ VisualStateManager.VisualStateGroups در کد بالا منظورم هست) ، مفسر xml در wpf اون را داخل پروپرتیِ Grid.Children میریزه دیگه؟
یعنی در واقع ، کد زیر اجرا میشه . درسته؟ :

کد:
<ControlTemplate x:Key="roundbutton" TargetType="Button">
    <Grid>
  
    <Grid.Children>
            <VisualStateManager.VisualStateGroups>
            <VisualStateGroup Name="CommonStates">
                <VisualState Name="Normal">
                </VisualState>
                <VisualState Name="MouseOver">
                </VisualState>
            </VisualStateGroup>
    </Grid.Children>
  
    </Grid>
</ControlTemplate>

اگه این طوره ، خوب پروپرتیِ Grid.Children که از نوع UIElementCollection هست اما شیِ داده شده ، یعنی VisualStateManager.VisualStateGroups ، از نوع VisualStateGroup هست که هیچ رابطه ی ارث بری ای با UIElement نداره . چرا این جوری هه پس؟
اگه این طور نیست ، پس چجوری هه و داخل کدوم پروپرتی از Grid ، ست میشه؟


دومین سئوال اینکه من اولین باره میبینم در کدهای xml ، بدون اینکه شی ای از ریشه ساخته بشه ، یهو عضو فرزندش (بدون اینکه شی ای از ریشه در تگ پدر ساخته بشه) ، فراخونی میشه . یعنی مگه در کد بالا ، نباید اول در تگ پدر ، VisualStateManager را بسازند و بعد در تگ فرزندش VisualStateManager.VisualStateGroups را ؟
یعنی نباید این جوری نوشته بشه؟ :

کد:
<ControlTemplate x:Key="roundbutton" TargetType="Button">
    <Grid>
  
    <VisualStateManager>
            <VisualStateManager.VisualStateGroups>
            <VisualStateGroup Name="CommonStates">
                <VisualState Name="Normal">
                </VisualState>
                <VisualState Name="MouseOver">
                </VisualState>
            </VisualStateGroup>
    </VisualStateManager>
  
    </Grid>
</ControlTemplate>
 

the_king

مدیرکل انجمن
الان وقتی داخل محتوا و content (منظورم content در xml هست . نه پروپرتیِ content) در Grid ، چیزی مینویسیم و تگ ای میذاریم (تگ VisualStateManager.VisualStateGroups در کد بالا منظورم هست) ، مفسر xml در wpf اون را داخل پروپرتیِ Grid.Children میریزه دیگه؟
نه. اون VisualStateManager.VisualStateGroups یک مشخصه الحاقی ئه، جزو مشخصه های Grid نیست. مثل همون Storyboard.TargetName که در پست #51 گفتم. در همون پست به این مساله اشاره کردم که هر چیزی که در بخش content نوشته میشه الزاما ربطی به مشخصه های اون کلاس نداره. بعضی ویژگی ها خاص WPF ئه، در #C دنبال هر چیزی که در WPF دیدید نگردید.

دومین سئوال اینکه من اولین باره میبینم در کدهای xml ، بدون اینکه شی ای از ریشه ساخته بشه ، یهو عضو فرزندش (بدون اینکه شی ای از ریشه در تگ پدر ساخته بشه) ، فراخونی میشه . یعنی مگه در کد بالا ، نباید اول در تگ پدر ، VisualStateManager را بسازند و بعد در تگ فرزندش VisualStateManager.VisualStateGroups را ؟
پدر و فرزندی در کار نیست، مثل IntPtr.Zero که Zero فیلد static ئه، Zero که فرزند IntPtr نیست، IntPtr رو می نویسیم تا struct اش مشخص بشه.
در واقع VisualStateGroupsProperty ئه که یک DependencyProperty ئه static بوده، اون VisualStateManager برای مشخص کردن کلاس ای است که VisualStateGroupsProperty بهش تعلق داره.
 

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

بالا