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

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
برای اینکه یاد بگیرید چشم بسته کد رو Copy / Paste نکنید. سطر به سطر تفسیرش کنید تا ببینید چه توصیفی می کنه. البته می توانستید در یک Style و با یک Setter صرفا مقدار BorderThickness رو 0 کنید و لزومی نداشت ControlTemplate جدید بسازید.

خیلی ممنون استاد .
کدهای خودم را خودم از اول مینویسم . کپی نمیکنم . اصلا دوست ندارم کدی را کپی کنم . اون template مایکروسافت را برای اینکه کدش را درک کنم ، کپی میکنم .
نه . نمیخوام BorderThickness را صفر کنم . کلا میخوام controltemplate ها را تمرین کنم .

در ضمن با TextBox مثل یک ContentControl رفتار کردید و برای کنترلی که ContentControl نبوده ContentPresenter تعریف کردید، خوب اونم تبدیل شده به یک چیزی بین TextBox و Label. چه چیزی در کد به نظرتون عجیبه؟

اصلا حواسم نبود که TextBox ، یه ContentControl نیست :green:
خوب برای نمایش Text در این نوع کنترل هایی که content control نیستن ، بجای استفاده از ContrntPresenter ، فقط باید پروپرتی Text شون را بایند یا templatebinding انجام داد؟ یا کارهای دیگه ای هم میشه انجام داد؟


متن داخل TextBox داخل Text قرار داره، طبعا اگر می خواهیم Text رو ویرایش کنیم مشخصه Text رو ویرایش می کنیم :
کد:
<TextBox Text="Sample"/>
یا :
کد:
            <TextBox>
                <TextBox.Style>
                    <Style TargetType="TextBox">
                        <Setter Property="Text" Value="Sample"/>
                    </Style>
                </TextBox.Style>
            </TextBox>
برای ساختن ComboBox اول Style و Template اش رو مطالعه می کنید تا ببینید اجزاء اش چیه.

خوب ، من که در کدم ، پروپرتیِ Content در ContentPresenter را به پروپرتیِ Text در کنترل TextBox ، بایند (TemplateBinding) کردم . (هر چند به قول شما چون TextBox از نوع ContentControl نیست ، نباید از ContentPresenter استفاده میکردم)
خوب شما که میگید در textbox وقتی چیزی بنویسم ، باعث میشه پروپرتیِ text اش تغییر کنه ، پس با این بایند ای (templatebinding) که انجام دادم ، باید Content در ContentPresenter هم تغییر کنه و بنابراین باید در صفحه اون متن تغییر کرده را نمایش بده دیگه .
مگه نه؟

نمیدونم ماهیت رو چی تعریف می کنید اما مثلا بصورت پیشفرض متن داخل TextBox خودش جداگانه ویرایش میشه، یعنی در کلاسش تعریفش شده که فرضا وقتی با صفحه کلید تایپ می کنید Text اش تغییر کنه، حتی اگه ظاهرش رو تغییر بدید. اما اینکه شما در ظاهر کنترل چی نمایش بدید طبعا روی عملکردش تاثیر میذاره :
کد:
                <ControlTemplate TargetType="TextBox" x:Key="MyTextBox">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition Width="30"/>
                        </Grid.ColumnDefinitions>
                        <ScrollViewer Margin="0" x:Name="PART_ContentHost" VerticalAlignment="Center"/>
                        <Border BorderBrush="{x:Static SystemColors.WindowFrameBrush}" BorderThickness="1" Grid.Column="0"/>
                        <Button Content="..." Grid.Column="1" Focusable="False"/>
                    </Grid>
                </ControlTemplate>
اون ScrollViewer بخشی است که متن داخلش نوشته میشه، فرضا اگه با یک TextBlock که Text اش Bind شده به Text کنترل تعویض اش کنید دیگه از چشمکزن و تغییرات ظاهری پیمایش TextBox خبری نیست.

خیلی ممنون
منم دقیقا خط مزبوط به ScrollViewer را متوجه نشدم .
مگه ScrollViewer برای زمانی بکار نمیره که محتوای مربوطه ، در حیطه ی صفحه نمایش نگنجه؟ (توی توضیحات مایکروسافت که انگار همچین چیزی نوشته)
خوب ، بنابراین وقتی فقط بخوایم به اندازه ی یه سطر و یه خط در textbox چیزی بنویسیم ، بنابراین ScrollViewer نباید ربطی به نمایش دادن متن textbox داشته باشه . اما داره . چرا؟
و اینکه آیا بجز ScrollViewer ، از شی دیگه یا هر کار دیگه ای برای نمایش و تغییر متن در textbox میتونیم استفاده کنیم؟ اگه آره ، چه شی یا چه روشی؟
خیلی ممنون استاد .:rose:
 

the_king

مدیرکل انجمن
خوب برای نمایش Text در این نوع کنترل هایی که content control نیستن ، بجای استفاده از ContrntPresenter ، فقط باید پروپرتی Text شون را بایند یا templatebinding انجام داد؟ یا کارهای دیگه ای هم میشه انجام داد؟
باز هم تکرار می کنم، باید به Style و Template شون مراجعه کنید و ببینید اون کنترل فلان چه اجزائی داره، فرضا برای ویرایشگر TextBox که چشمکزن و Selection داخل ویرایشگر داره، داشتن یک ScrollViewer خاص لازمه که فرضا نامش صریحا فلان ئه، نه هر اسم دیگری. یک مورد کلی نیست، هر کنترل ای اجزاء و مشخصات خودش رو می طلبه.
مثلا کلاس TextBox که نمیدونه ScrollViewer ای که بهش نام "x:Name="DiegoMaradona می دهید باید محل قرار گرفتن چشمکزن و ویرایشگر باشه. اون "x:Name="PART_ContentHost یک نامگذاری الکی و همینطوری نیست.

خوب ، من که در کدم ، پروپرتیِ Content در ContentPresenter را به پروپرتیِ Text در کنترل TextBox ، بایند (TemplateBinding) کردم . (هر چند به قول شما چون TextBox از نوع ContentControl نیست ، نباید از ContentPresenter استفاده میکردم)
خوب شما که میگید در textbox وقتی چیزی بنویسم ، باعث میشه پروپرتیِ text اش تغییر کنه ، پس با این بایند ای (templatebinding) که انجام دادم ، باید Content در ContentPresenter هم تغییر کنه و بنابراین باید در صفحه اون متن تغییر کرده را نمایش بده دیگه .
مگه نه؟
بله، برای همین گفتم یک چیزی بین TextBox و Label شده.

خیلی ممنون
منم دقیقا خط مزبوط به ScrollViewer را متوجه نشدم .
مگه ScrollViewer برای زمانی بکار نمیره که محتوای مربوطه ، در حیطه ی صفحه نمایش نگنجه؟ (توی توضیحات مایکروسافت که انگار همچین چیزی نوشته)
خوب ، بنابراین وقتی فقط بخوایم به اندازه ی یه سطر و یه خط در textbox چیزی بنویسیم ، بنابراین ScrollViewer نباید ربطی به نمایش دادن متن textbox داشته باشه . اما داره . چرا؟
یک مساله ای خیلی واضح ئه، هم در WPF و هم در Windows Forms وقتی یک TextBox با کادر مشخصی دارید می توانید متنی داخلش بنویسید که از اون کادر بزرگتر باشه و با کلید های مکان نما یا ماوس پیمایش اش کنید، حالا جهت افقی و یا عمودی بودن پیمایش محل بحث نیست، اما به هر حال Scroll پذیر بودن جزئی از ماهیت TextBox بوده و هست.
اما شما که وجود ScrollViewer رو بی ربط تلقی می کنید، آیا کد کلاس TextBox رو خودتون طراحی کردید؟ یا حداقل میدونید داخلش چه چیزی برای چه موردی بکار میره و چی به چی مربوطه؟
وقتی میگید "ScrollViewer نباید ربطی به نمایش دادن متن textbox داشته باشه" باید بشه این نتیجه رو گرفت که میدونید داخل TextBox چه کدی نوشته شده و میدونید که کارکردش ربطی به وجود ScrollViewer نداره.
در حالی که همچین اطلاعاتی رو احتمالا ندارید. خود مایکروسافت در TextBox ControlTemplate Example از ScrollViewer استفاده کرده، بیخودی که اینکار رو نکرده، حتما به کارکردش مرتبط بوده که در ControlTemplate اش یک ScrollViewer رو با نام خاصی توصیف کرده.

و اینکه آیا بجز ScrollViewer ، از شی دیگه یا هر کار دیگه ای برای نمایش و تغییر متن در textbox میتونیم استفاده کنیم؟ اگه آره ، چه شی یا چه روشی؟
شما دارید برای TextBox که کلاس و کدنویسی مشخص و خاص خودش رو داره ControlTemplate می سازید، پس باید بر اساس مشخصات اون کلاس خاص Template طراحی کنید.
انگار که خیاط هستید و یک مرد درشت هیکل بهتون مراجعه کرده و دارید برایش کت و شلوار می دوزید. طبعا باید با الگوی مناسب همچین قد و قواره ای پیش برید، با الگوی لباس نوزاد یا دخترانه که نمی توانید برای همچین قد و هیکلی لباس طراحی کنید. اگر بخواهید اون ScrollViewer رو با چیز دیگر جایگزین کنید، یک بخش اساسی که کارکرد کلاس TextBox بهش وابسته است رو از کار انداختید.
 

SajjadKhati

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

فرضا برای ویرایشگر TextBox که چشمکزن و Selection داخل ویرایشگر داره، داشتن یک ScrollViewer خاص لازمه که فرضا نامش صریحا فلان ئه، نه هر اسم دیگری. یک مورد کلی نیست، هر کنترل ای اجزاء و مشخصات خودش رو می طلبه.
مثلا کلاس TextBox که نمیدونه ScrollViewer ای که بهش نام "x:Name="DiegoMaradona می دهید باید محل قرار گرفتن چشمکزن و ویرایشگر باشه. اون "x:Name="PART_ContentHost یک نامگذاری الکی و همینطوری نیست.

بله، برای همین گفتم یک چیزی بین TextBox و Label شده.


یک مساله ای خیلی واضح ئه، هم در WPF و هم در Windows Forms وقتی یک TextBox با کادر مشخصی دارید می توانید متنی داخلش بنویسید که از اون کادر بزرگتر باشه و با کلید های مکان نما یا ماوس پیمایش اش کنید، حالا جهت افقی و یا عمودی بودن پیمایش محل بحث نیست، اما به هر حال Scroll پذیر بودن جزئی از ماهیت TextBox بوده و هست.
اما شما که وجود ScrollViewer رو بی ربط تلقی می کنید، آیا کد کلاس TextBox رو خودتون طراحی کردید؟ یا حداقل میدونید داخلش چه چیزی برای چه موردی بکار میره و چی به چی مربوطه؟
وقتی میگید "ScrollViewer نباید ربطی به نمایش دادن متن textbox داشته باشه" باید بشه این نتیجه رو گرفت که میدونید داخل TextBox چه کدی نوشته شده و میدونید که کارکردش ربطی به وجود ScrollViewer نداره.
در حالی که همچین اطلاعاتی رو احتمالا ندارید. خود مایکروسافت در TextBox ControlTemplate Example از ScrollViewer استفاده کرده، بیخودی که اینکار رو نکرده، حتما به کارکردش مرتبط بوده که در ControlTemplate اش یک ScrollViewer رو با نام خاصی توصیف کرده.


شما دارید برای TextBox که کلاس و کدنویسی مشخص و خاص خودش رو داره ControlTemplate می سازید، پس باید بر اساس مشخصات اون کلاس خاص Template طراحی کنید.
انگار که خیاط هستید و یک مرد درشت هیکل بهتون مراجعه کرده و دارید برایش کت و شلوار می دوزید. طبعا باید با الگوی مناسب همچین قد و قواره ای پیش برید، با الگوی لباس نوزاد یا دخترانه که نمی توانید برای همچین قد و هیکلی لباس طراحی کنید. اگر بخواهید اون ScrollViewer رو با چیز دیگر جایگزین کنید، یک بخش اساسی که کارکرد کلاس TextBox بهش وابسته است رو از کار انداختید.


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

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

یا اگه همچین سایتی را نمیشناسین ، پس بگین شما از کجا متوجه شدین که مثلا کنترل textbox ، مهم ترین کمپوننت اش ، کمپوننت scrollviewer هست؟
از جایی خوندین یا صرفا توسط مثال هایی که از template در سایت مایکروسافت هست متوجه شدین؟

و دومین مشکل ام هم همین نام خاص هه . نام را از کجا باید متوجه بشیم که چی بذاریم؟
از مثال های template در مایکروسافت یا بصورت رسمی ، در سایتی یا کلا در جایی با توضیحات بیشتری داده؟
 

the_king

مدیرکل انجمن
خیلی ممنون استاد .
بله . Template ها را نگاه میکنم .
ولی Template های مایکروسافت ، فقط یک مثال هست.
فقط مثال نیست، نوشته This topic describes the styles and templates for the TextBox control.
ننوشته This topic describes an example یا This topic describes a sample.
داره ساختار پیشفرضش رو نشون میده، هر چیزی که در ساختارش تعریف شده باشه در اون قالب پیشفرض هست. اجزاء اضافی و غیر اجباری ظاهری هم طبعا ممکنه داشته باشه ولی هر چی که وجودش ضروری است داخلش هست.
مشکل من اینه که اولا با اجزا و کمپوننت های تشکیل دهنده ی یک کنترل آشنا نیستم . الان مثلا نمیدونستم که textbox ، از کمپوننت و مولفه ی scrollviewer هم تشکیل شده .
این مشکل این نیست که نمیدونید، مشکل اینه که نگاه نمی کنید ببینید چی داخلش هست تا بدونید. من الان جای شما، فرضا نمی دونم اجزاء داخل کنترل ABCD چیه. چیکار می کنم؟ میرم در سایت مایکروسافت صفحه ABCD Styles and Templates رو می بینم و می فهمم داخل ControlTemplate اش چه اجزائی توصیف شده، به همین سادگی.

سئوال مهم اینه که سایتی را میشناسین که درباره ی کمپوننت و مولفه های مختلفِ کنترل ها بحث کنه (یا حداقل نام ببره) ؟ یا حداقل کمپوننت های اساسیِ اون کنترل را نام ببره؟ منظورم از کمپوننت اساسی اینه که اون کنترل ، بدون اون کمپوننت ، کار نمیکنه و یا با مشکل اساسی رو به رو میشه (مثل کمپوننت scrollviewer در textbox) .
مثلا بگه که کنترل textbox از کمپوننت اساسی scrollviewer تشکیل شده (حالا کمپوننت های border و اینها را بگه یا نگه ، مهم نیست) .
قبلا بهتون گفتم، سایت سازنده، سایت مایکروسافت. البته همه اجزاء اون کنترل ها اساسی و مهم هستند، جزء اضافی خاصی نداره، گل و پروانه که دورش نذاشته.
اما بصورت کلی هر جزئی که در کد کلاس استفاده شده نامگذاری شده و Name یا x:Name ای داره، اگه نام نداشته باشه به احتمال زیاد نقشی در کد نویسی نداره، نه اینکه مهم نباشه، اما اگر حذف کنید به احتمال زیاد در کارکرد کد تاثیری نداره.
سایتی که باید بگه چی مهمه و چی مهم نیست بر اساس نظر کی بگه؟ از نظر من شاید اصلا خود چشمکزن هم مهم نباشه. مهم و غیر مهم عیار علمی نداره، در مستندات فنی سنجش با معیار های علمی ئه.
در ضمن شاید از نظر شما Border یک کادر بی اهمیت باشه ولی عموما برای کاربر مهمه که از طریق ظاهر Border و ... بتونه بفهمه این کنترل Enabled هست یا نه، Focus داره یا نه، Hover شده یا نه و ...
کلا دیدن تفاوت عملکرد یک ControlTemplate ای که فقط ScrollViewer رو داره با تفاوت عملکرد Template پیشفرض کار راحتی ئه. می توانید مقایسه شون کنید و ببینید چقدر ناقص میشه.

یا اگه همچین سایتی را نمیشناسین ، پس بگین شما از کجا متوجه شدین که مثلا کنترل textbox ، مهم ترین کمپوننت اش ، کمپوننت scrollviewer هست؟
مهم و غیر مهم و مهمترین و کم اهمیت ترین و خفن و بیخودی و ... نداره. من نه از این اسم گذاری های غیر فنی تون سر در میارم و نه اعتقادی به این دارم که ScrollViewer مهمترین جزء TextBox ئه.
من هر چیزی که در قالب پیشفرض TextBox ببینم جزو اجزاء اساسی TextBox میدونم. اصلا اعتقادی به اضافی و مهم نبودن اجزاء قالب پیشفرض در کنترل ها ندارم، اونم کنترل های مایکروسافت که همیشه روی سادگی و مختصر مفید بودن در طراحی اجزاء تاکید داشته.

و دومین مشکل ام هم همین نام خاص هه . نام را از کجا باید متوجه بشیم که چی بذاریم؟
اصلا مشکلی نیست، در همون قالب پیشفرض اسامی اجزاء مشخص شده، بچه شما نیست که بخواهید تصمیم بگیرید که رویش چه اسمی بذارید، اون اجزاء کنترل TextBox ئه، باید همون اسامی بمونه تا بتونه پیداشون کنه.
مگر اینکه کدی مشابه کلاس TextBox رو بنویسید و در اون کلاس اسامی دیگری رو بکار ببرید. مادامی که از کلاس های موجود استفاده می کنید باید از مشخصات اجزاء داخل Template پیشفرض پیروی کنید.
از مثال های template در مایکروسافت یا بصورت رسمی ، در سایتی یا کلا در جایی با توضیحات بیشتری داده؟
منبع اصلی که همیشه سایت مایکروسافت ئه و خواهد ماند. اینترنت یک محیط پویا است، هر روز ممکنه منبع جدیدی ایجاد بشه. باید جستجو کنید. شاید باشه.
 

SajjadKhati

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

SajjadKhati

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

کد:
        <ComboBox Name="myComboBox" Height="28" Margin="10,295.606,0,0"  VerticalAlignment="Top" Width="201.111" SelectedIndex="0" Background="#FF2300FF" BorderBrush="Red" HorizontalAlignment="Left" RenderTransformOrigin="0.5,0.5">
            <ComboBox.Items>
                <System:String>salam</System:String>
                <System:String>khobi?</System:String>
            </ComboBox.Items>
            <ComboBox.ItemContainerStyle>
                <Style TargetType="ComboBoxItem">
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="BorderBrush" Value="Red"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </ComboBox.ItemContainerStyle>
        </ComboBox>

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

the_king

مدیرکل انجمن
خیلی ممنون استاد .
پس باید مثال های مایکروسافت را دید .
استاد ، میگم وقتی حداقل داشت wpf را طراحی میکرد ، چرا یه دفعه نیومد برای جزئیات و ظاهر کنترل ها ، حداقل پروپرتی های بیشتری برای رنگ های بخش های مختلف از یه کنترل در نظر بگیره؟
مثلا برای کمبوباکس اگه 2 تا 3 پروپرتیِ بیشتری برای انتخاب رنگ بخش های مختلف اش در نظر میگرفت ، خیلی اوقات دیگه لازم به استفاده از تمپلیت نبود .
نه به کنترل های تلریک که این قدر برای ریزترین جزئیات اش ، انواع پروپرتی ها را در نظر میگیره که آدم برای استفاده از یه کنترل ساده ای مثل کمبوباکس اش گیج میشن و نه به طراحی پیش فرض کنترل های مایکروسافت که زیبایی نسبی را هم در نظر نمیگیره.
هر طراحی نظر خودش رو داره، محاله سبک ای پیاده بشه که با سلیقه و نظر همه جور در بیاد.
مشخصه های ظاهری کنترل در WPF کمتر از Windows Forms اهمیت دارند چون Style و Template برای این منظور استفاده میشه.
لیست مشخصه های ظاهری ComboBox رو ببینید، مشخصه های خاص ComboBox نیستند، مشخصه های به ارث رسیده از Control هستند، خیلی کلی که برای هر جور کنترلی کاربرد داشته باشه.
اگر برای ComboBox یا هر کنترلی مشخصه فلان برای رنگ بهمان تعریف بشه، نیاز به کد نویسی در کلاس داره و این برای طراحی که نمیخواد اون بخش به اون شکل باشه یا با رنگ خاصی مشخص بشه محدودیت ایجاد می کنه.
دست طراحی که میخواد ظاهر کاملا متفاوتی بده رو می بنده، فرضا محدودش می کنه به انتخاب رنگ برای فلان قسمت.

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

کد:
        <ComboBox Name="myComboBox" Height="28" Margin="10,295.606,0,0"  VerticalAlignment="Top" Width="201.111" SelectedIndex="0" Background="#FF2300FF" BorderBrush="Red" HorizontalAlignment="Left" RenderTransformOrigin="0.5,0.5">
            <ComboBox.Items>
                <System:String>salam</System:String>
                <System:String>khobi?</System:String>
            </ComboBox.Items>
            <ComboBox.ItemContainerStyle>
                <Style TargetType="ComboBoxItem">
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="BorderBrush" Value="Red"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </ComboBox.ItemContainerStyle>
        </ComboBox>

کجا و چه پروپرتی را باید مقداردهی کنم یا کلا باید چی کار کنم تا درست بشه؟
خیلی ممنون
مثلا اینطوری :
کد:
        <ComboBox Name="myComboBox" Height="28" Margin="10,295.606,0,0"  VerticalAlignment="Top" Width="201.111" SelectedIndex="0" Background="#FF2300FF" BorderBrush="Red" HorizontalAlignment="Left" RenderTransformOrigin="0.5,0.5">
            <ComboBox.Items>
                <system:String>salam</system:String>
                <system:String>khobi?</system:String>
            </ComboBox.Items>
            <ComboBox.ItemContainerStyle>
                <Style TargetType="ComboBoxItem">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ComboBoxItem}">
                                <Border x:Name="Border" Background="{TemplateBinding Background}">
                                    <ContentPresenter />
                                </Border>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsHighlighted" Value="True">
                                        <Setter Property="Background" TargetName="Border" Value="Red" />
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ComboBox.ItemContainerStyle>
        </ComboBox>
 

SajjadKhati

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


مثلا اینطوری :
کد:
        <ComboBox Name="myComboBox" Height="28" Margin="10,295.606,0,0"  VerticalAlignment="Top" Width="201.111" SelectedIndex="0" Background="#FF2300FF" BorderBrush="Red" HorizontalAlignment="Left" RenderTransformOrigin="0.5,0.5">
            <ComboBox.Items>
                <system:String>salam</system:String>
                <system:String>khobi?</system:String>
            </ComboBox.Items>
            <ComboBox.ItemContainerStyle>
                <Style TargetType="ComboBoxItem">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ComboBoxItem}">
                                <Border x:Name="Border" Background="{TemplateBinding Background}">
                                    <ContentPresenter />
                                </Border>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsHighlighted" Value="True">
                                        <Setter Property="Background" TargetName="Border" Value="Red" />
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ComboBox.ItemContainerStyle>
        </ComboBox>

خیلی ممنون استاد .
الان ItemContainerStyle ، استایلِ مربوط به یک آیتم در لیست کمبوباکس هست (مثلا در مثال بالا ، منظورش فقط salam یا khobi میشه) یا اینکه کلِ آیتم ها منظور شه (یعنی هم salam و هم khobi) ؟
مشکل من از این بود که border نذاشتم یا پروپرتیِ مورد نظر در تریگر را درست ننوشتم؟
بعد اینکه بجای کد بالا که border را درون تریگر ننوشتین ، میتونین مستقیما border را درون تریگر بنویسین دیگه . درسته؟


بعد اینکه قبلا که سئوال پرسیده بودم که اگه مثلا کنترلی را در تگ ای تعریف کردیم و در یک تگِ دیگه (که اون تگ ، جزء فرزندانش نباشه و کلا در تگ مجزایی باشه) بخوایم بهش (به تگی که قبلا تعریف کردیم) دسترسی پیدا کنیم ، چی کار میکنیم؟ جوابش اینه که مثل کاری که شما در کد کردین ، پروپرتیِ Name را براش در نظر میگیریم . درسته؟
بعد اینکه گفته بودین اون پیشوند x بخاطر این در پروپرتی هایی مثل Name در بعضی از تگ ها میاد چون کلاس های اون ها ، اون عضوِ Name را نداره . پس چرا در کلاس Border که عضو Name داره ، علاوه بر المنت Name ، المنت x:Name هم میاد؟ و اینکه فرقی داره که کدوم را مقداردهی کنیم؟
 

the_king

مدیرکل انجمن
خیلی ممنون استاد .
الان ItemContainerStyle ، استایلِ مربوط به یک آیتم در لیست کمبوباکس هست (مثلا در مثال بالا ، منظورش فقط salam یا khobi میشه) یا اینکه کلِ آیتم ها منظور شه (یعنی هم salam و هم khobi) ؟
همه شون. Style ای که نام نداشته باشه برای هر جزء ای که با نوع اش جور در بیاد شامل میشه، البته در جایی که اون Style تعریف شده دسترسی داره، یعنی همه ComboBoxItem های اون ComboBox.

مشکل من از این بود که border نذاشتم یا پروپرتیِ مورد نظر در تریگر را درست ننوشتم؟
نه. مشکل این بود که داشتید رنگ مشخصه ای رو تغییر میدادید که تغییرش تاثیری نداره. یک Border در اون Style هست که باید زمینه اون Border عوض بشه.
شما دارید رنگ زمینه ComboBoxItem رو تغییر می دهید، اما داخلش Border ای قرار داره که رنگش کاری به اون مشخصه نداره.
دقیقا مثل این مثالی که میزنم نیست چون Grid به مشخصه Background اهمیت میده، ولی نتیجه اش شبیه به این شده که زمینه Grid ای رو قرمز کنید، در حالی که Border داخلش رنگ زمینه آبی داره، اون قرمز کردن بی فایده انجام میشه، چون تاثیر ظاهری نخواهد داشت :
کد:
        <Grid Background="Red">
            <Border Background="Blue"/>
        </Grid>

بعد اینکه بجای کد بالا که border را درون تریگر ننوشتین ، میتونین مستقیما border را درون تریگر بنویسین دیگه . درسته؟
یعنی Border رو داخل Trigger تعریف کنم؟ سر در نمیارم منظورتون چه جور کدی ئه.

بعد اینکه قبلا که سئوال پرسیده بودم که اگه مثلا کنترلی را در تگ ای تعریف کردیم و در یک تگِ دیگه (که اون تگ ، جزء فرزندانش نباشه و کلا در تگ مجزایی باشه) بخوایم بهش (به تگی که قبلا تعریف کردیم) دسترسی پیدا کنیم ، چی کار میکنیم؟ جوابش اینه که مثل کاری که شما در کد کردین ، پروپرتیِ Name را براش در نظر میگیریم . درسته؟
نه. این رو با اون موضوع قاطی نکنید، اونجا فرضا می خواستید یک Border با نام "Border" رو توصیف کنید که بعدا بیایید مشخصه فلان اش رو مقدار دهی کنید. یعنی میخواستید در مورد مقدار دهی شیء ای برنامه ریزی کنید که قبلا ایجاد شده و منحصر بفرد ئه. شما نمی توانید فرضا داخل خود Border یک Setter بسازید، حتی اگه برای اون Border نامی در نظر بگیرید برای اینکار بدرد نمی خوره.

اما اینجا ما در مورد Border منحصر بفردی برنامه ریزی نمی کنیم. اسامی داخل اجزاء Style و Template منحصر بفرد نیستند چون اشیاء مرتبط در آینده ایجاد می شوند، برای هر المنت ای که از اون Style و Template استفاده کننده قابل استفاده هستند. داریم در مورد همه Border های "Border" ای برنامه ریزی می کنیم که در همه ComboBoxItem ها ایجاد خواهند شد، یعنی برای همه ComboBoxItem ها صدق می کنه، نه یک Border منحصر بفرد، یک ComboBoxItem خاص و یک "Border" منحصر بفرد نیست. اون نام "Border" نام یک المنت خاص در صفحه نیست.
Setter یک برنامه ریزی برای آینده است، مثلا زمانی که کنترل یا کنترل هایی داشتیم که Style اش فلان بود یا Template اش بهمان بود. در Setter در مورد اشیاء ای برنامه ریزی میشه که هنوز ایجاد نشدن.
این نام صرفا برای یک ارجاع کلی ئه، نام کنترل فلان نیست.
برای همین نام ای هم که بکار می بریم یکتا نیست. این یک تفاوت بزرگ با اون موضوع داره، اونجا می خواستید فرضا یک Border بسازید و بعد مشخصه فلان اش رو مقدار دهی کنید، اینجا صحبت Style و Template ئه، هنوز حتی یک کنترل که از اون Style استفاده می کنه فراخوانی نشده، نام ای که مشخص می کنیم برای همه اون اجزاء ای که در آینده ایجاد می شوند و اون Style و Template رو دارند صدق می کنه.

بعد اینکه گفته بودین اون پیشوند x بخاطر این در پروپرتی هایی مثل Name در بعضی از تگ ها میاد چون کلاس های اون ها ، اون عضوِ Name را نداره . پس چرا در کلاس Border که عضو Name داره ، علاوه بر المنت Name ، المنت x:Name هم میاد؟ و اینکه فرقی داره که کدوم را مقداردهی کنیم؟
قبلا پرسیدید و جواب این سوال رو در پست 85# دادم.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلامی مجدد استاد .
من تازه متوجه ی این شدم که از کجا متوجه بشم که چه المنت ها و کنترل هایی برای ساخت تمپلیت (برای یک کنترل) ، ضروری هه .
اول باید توی بخش "Control Styles and Templates" در سایت مایکروسافت بریم . مثلا برای textbox میشه "TextBox Styles and Templates" که در لینک زیر هست (که تا اینجا را میدونستم) :

TextBox Styles and Templates - WPF

بعد قسمت "Control Parts" را ببینیم . مثلا برای textbox میشه "TextBox Parts" .
و البته هر Parts دیگه . چون ممکنه از چندین Parts تشکیل شده باشن .
توی این بخش های Parts :
اولا در قسمت Type ببینیم چه نوع کنترل هایی را گفت . هر کنترلی را گفت ، اون ها کنترل ، کنترل های ضروری برای ساخت تمپلیت ها هستند . (البته کنترل هایی مثل ContentPresenter و ScrollContentPresenter بحث شون جداست) .
دوما در بخش Part باید ببینیم که نام اون کنترل (که در بخش Type معرفی کرد و باید بسازیم) (یعنی پروپرتی Name یا x:Name از اون کنترل) را چی باید بذاریم و حتما هم باید نام اش را همونی که گفت بذاریم تا کار کنه (یا اینکه کامل کار کنه) .

بنابراین چون در TextBox Styles and Templates گفت که کنترل از نوع FrameworkElement میخواد ، من کنترل Border را (از کدی که شما داده بودین را) فقط گذاشتم و اسم این کنترل Border را هم PART_ContentHost گذاشتم و بنابراین کار کرد .
کد زیر :

کد:
<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPF_Practice"
        xmlns:System="clr-namespace:System;assembly=mscorlib" x:Class="WPF_Practice.Window1"
        mc:Ignorable="d"
        Title="Window1" Height="450" Width="800">

    <Grid x:Name="myGrid1">
            <Grid.Resources>

            <ControlTemplate TargetType="TextBox" x:Key="TextBoxPracties">
                <Border Name="PART_ContentHost" BorderBrush="Red" BorderThickness="2" />
            </ControlTemplate>

            </Grid.Resources>
       
       
            <TextBox Template="{StaticResource TextBoxPracties}" HorizontalAlignment="Left" Height="83" Margin="10,83,0,0" TextWrapping="Wrap" Text="my text box 1" VerticalAlignment="Top" Width="234"/>
   
    </Grid>

</Window>

یه سئوال اینکه چرا باید بعضی وقت ها کدها را بجای اضافه کردن در Grid.Resource ، باید در Window.Resource اضافه کنیم تا کار کنه؟
یه جا دیدم که کد در Grid.Resource ام کار نکرد و در Window.Resource که گذاشتم ، کار کرد (کد بالا را نمیگم) .

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

the_king

مدیرکل انجمن
یه سئوال اینکه چرا باید بعضی وقت ها کدها را بجای اضافه کردن در Grid.Resource ، باید در Window.Resource اضافه کنیم تا کار کنه؟
یه جا دیدم که کد در Grid.Resource ام کار نکرد و در Window.Resource که گذاشتم ، کار کرد (کد بالا را نمیگم) .
باید مثال بزنید، بدون مثال نمی تونم جواب بدم.
 

SajjadKhati

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

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

کد:
            <ControlTemplate TargetType="TextBox" x:Key="TextBoxPracties">
                <Grid>
                    <Border  BorderBrush="Red" BorderThickness="2" />
                    <Ellipse Stroke="Black" Fill="DeepSkyBlue"/>
                    <ScrollViewer Name="PART_ContentHost" Margin="0"/>
                </Grid>
            </ControlTemplate>

اگه بخوایم وقتی تعداد خط ها ، از ناحیه و ارتفاع textbox مون بالاتر زد ، اسکرول به نمایش در بیاد ، باید چه کدی بنویسیم و چی کار کنیم؟
همچنین میتونیم کاری کنیم که کاربر بتونه فقط یک خط بنویسه یا کلا به اندازه ای که اندازه و ارتفاع textbox هست بنویسه و بیشتر از اون ننویسه؟
 

the_king

مدیرکل انجمن
سلامی مجدد .
آها . پس هر وقت گیرم اومد مثال میزنم . چون قبلا یه کدی بود که الان نمیدونم .

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

کد:
            <ControlTemplate TargetType="TextBox" x:Key="TextBoxPracties">
                <Grid>
                    <Border  BorderBrush="Red" BorderThickness="2" />
                    <Ellipse Stroke="Black" Fill="DeepSkyBlue"/>
                    <ScrollViewer Name="PART_ContentHost" Margin="0"/>
                </Grid>
            </ControlTemplate>

اگه بخوایم وقتی تعداد خط ها ، از ناحیه و ارتفاع textbox مون بالاتر زد ، اسکرول به نمایش در بیاد ، باید چه کدی بنویسیم و چی کار کنیم؟
همچنین میتونیم کاری کنیم که کاربر بتونه فقط یک خط بنویسه یا کلا به اندازه ای که اندازه و ارتفاع textbox هست بنویسه و بیشتر از اون ننویسه؟
TextBox مشخصه های VerticalScrollBarVisibility و HorizontalScrollBarVisibility و البته AcceptsReturn برای TextBox های چند سطری داره.
توجه داشته باشید که ScrollViewer خودش Style و ControlTemplate داره و داخل ControlTemplate اش برای ScrollBar ئه Visibility رو Bind کرده اند.
طبعا وقتی AcceptsReturn ئه در TextBox برابر False باشه و TextWrapping هم NoWrap باشه، نمیتونه بره سطر بعدی و یک سطری میشه.
برای محدود کردن تعداد سطر مشخصه آماده نداره، مثل Windows Forms ئه، خودتون در رخداد هایی مثل TextChanged و PreviewTextInput به شیوه دلخواه تون کنترلش می کنید.
 

SajjadKhati

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

استاد ، میشه برای یک افکت ای (مثل افکت BlurEffect) که برای یه کنترل اِعمال میکنیم ، یه clip تعیین کنیم تا فقط در محدوده ی اون کلیپ ، افکت مون درونِ اون کنترل ، اِعمال بشه تا در تمام اون کنترل ، اون افکت ، اِعمال نشه؟
یعنی پروپرتیِ clip که در هر کنترل هست و باعث میشه اون شی Geometry ای که بهش میدیم ، فقط اون قسمت ها را رسم و رندر کنه ؛ آیا میشه همچین کاری را با افکت ها هم انجام داد؟ اگه آره ، چجوری؟

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

CodePlex Archive

اما فقط 5 تا افکت داره . افکت درخشندگی هم نداره .

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

خیلی ممنون .
 

the_king

مدیرکل انجمن
آها . خیلی ممنون استاد .
هم تشکری مجدد از اینکه وقت جواب دادن برام میذارید :rose:

استاد ، میشه برای یک افکت ای (مثل افکت BlurEffect) که برای یه کنترل اِعمال میکنیم ، یه clip تعیین کنیم تا فقط در محدوده ی اون کلیپ ، افکت مون درونِ اون کنترل ، اِعمال بشه تا در تمام اون کنترل ، اون افکت ، اِعمال نشه؟
یعنی پروپرتیِ clip که در هر کنترل هست و باعث میشه اون شی Geometry ای که بهش میدیم ، فقط اون قسمت ها را رسم و رندر کنه ؛ آیا میشه همچین کاری را با افکت ها هم انجام داد؟ اگه آره ، چجوری؟
Clip برای همه رسم های داخل کنترل ئه، که شامل Effect هم میشه. صرفا برای Effect یک Clip اختصاصی وجود نداره.
برای ساختن فیلتر های اختصاصی در مورد ShaderEffect مطالعه و جستجو کنید.

بعد اینکه توی winform ، وقتی متد یا رویدادی را از جایی فراخونی میکردیم ، در جایی که اون متد یا رویداد یا پروپرتی که نوشته و تعریف کرده بودیم ، تعداد فراخونی ها را مینوشت و با کلیک روی اون نوشته ، میتونستیم به اون خط ای بریم که اون متد فراخونی شده بود . اما توی کدهای سی شارپ در wpf من ، این نوشته ها نمیان . اوایل فکر کنم بود . الان دیگه نیست . تا جایی که یادم میاد ، تنظیمات خاصی را دست نزدم . چجوری میشه این قضیه و این نوشته های بالای هر متد و رویداد و پروپرتی را آورد؟
در تنظیمات Options ویژوال استدیو یک کادر برای جستجو هست، CodeLens رو در اون کادر جستجو کنید.
 

SajjadKhati

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

سلامی مجدد
خیلی ممنون استاد :rose:
بله میدونم .
ولی منظورم این بود که همه ی رسم های داخل کنترل انجام بشه اما اون افکت ، فقط روی بخشی از کنترل که ما مشخص میکنیم ، اِعمال بشه .
حالا مهم نیست .

برای ساختن فیلتر های اختصاصی در مورد ShaderEffect مطالعه و جستجو کنید.

دقیق متوجه نشدم .
منظورتون اینه که با ShaderEffect میتونم همه ی اون افکت هایی که مد نظرمه را اجرا کنم؟

در تنظیمات Options ویژوال استدیو یک کادر برای جستجو هست، CodeLens رو در اون کادر جستجو کنید.

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

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

استاد ، در tabcontrol (زیر) :

1.JPG

همونطور که میبینید ، زیرِ TabItem هاش (سمت راست) ، transparent هست و کنترلِ پشت اش مشخص هه (که آبی هست) . اگه بخوام فقط این قسمت (یعنی بخش سمت راست که زیرِ Second که نوشته ، خالی هست) را خودم رسم کنم و کلا پُر کنم ، باید برای کدوم بخش از کنترل TabControl ، تمپلیت یا استایل بنویسم؟ :

1) پروپرتی ItemContainerStyle (مربوط به TabControl)
2) پروپرتی Template (مربوط به TabItem)
3) پروپرتی Template (مربوط به TabControl)

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


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

the_king

مدیرکل انجمن
دقیق متوجه نشدم .
منظورتون اینه که با ShaderEffect میتونم همه ی اون افکت هایی که مد نظرمه را اجرا کنم؟
من از کجا باید بدونم همه افکت های مد نظر در ذهن شما چیه، در مورد ShaderEffect مطالعه کنید تا ببینید چه قابلیت هایی داره و چه افکت هایی میشه باهاش ساخت.

استاد ، در tabcontrol (زیر) :

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

همونطور که میبینید ، زیرِ TabItem هاش (سمت راست) ، transparent هست و کنترلِ پشت اش مشخص هه (که آبی هست) . اگه بخوام فقط این قسمت (یعنی بخش سمت راست که زیرِ Second که نوشته ، خالی هست) را خودم رسم کنم و کلا پُر کنم ، باید برای کدوم بخش از کنترل TabControl ، تمپلیت یا استایل بنویسم؟ :

1) پروپرتی ItemContainerStyle (مربوط به TabControl)
2) پروپرتی Template (مربوط به TabItem)
3) پروپرتی Template (مربوط به TabControl)
برای TabItem

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

کلا یه کم درباره ی تمپلیت های مختلف در کنترل هایی که چند قسمت دارند مثل همین کنترل tabcontrol ، یه کم توضیح میدین که ما از کجا متوجه بشیم کدوم تمپلیت اش برای کجاست؟
معمولا وقتی یک Style در Document تون کد نویسی می کنید که در همون Document روی کنترل یا کنترل هایی اعمال شده، وقتی روی کدش جابجا می شوید در یکی از کنترل ها ناحیه رو مشخص می کنه.
غیر از اون هم اگه خارج از ControlTemplate بصورت یک مجموعه المنت درج اش کنید در نمایش صفحه نشون میده که این بخش از کد که انتخاب کردید کجا داره نشون داده میشه.
 

SajjadKhati

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

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

برای TabItem


برای TabItem


معمولا وقتی یک Style در Document تون کد نویسی می کنید که در همون Document روی کنترل یا کنترل هایی اعمال شده، وقتی روی کدش جابجا می شوید در یکی از کنترل ها ناحیه رو مشخص می کنه.
غیر از اون هم اگه خارج از ControlTemplate بصورت یک مجموعه المنت درج اش کنید در نمایش صفحه نشون میده که این بخش از کد که انتخاب کردید کجا داره نشون داده میشه.

منظورتون گزینه ی شماره ی 2 ای که در پست قبلی گفتم ، هست؟
اگه آره ، من پروپرتی Template (مربوط به TabItem) را مقدار دادم اما فقط همون آیتم را میتونم از نو بسازم .
اون قسمت پایین اش که Transparent هست را نمیتونم . برای این قسمتِ Transparent ، انگار پروپرتیِ TabControl.ItemContainerStyle را باید استایل بدم .

این کار را انجام دادم (یعنی پروپرتیِ TabControl.ItemContainerStyle را استایل دادم) . و کدم هم ، کد زیر هست :

کد:
        <TabControl HorizontalAlignment="Left" Height="181" Margin="382,16,0,0" VerticalAlignment="Top" Width="400" Background="#FF939393" BorderThickness="2" RenderTransformOrigin="0.5,0.5" IsSynchronizedWithCurrentItem="False" BorderBrush="#FF8D8D8D" Foreground="Black" TabStripPlacement="Right">
            <TabControl.ItemContainerStyle >
                <Style TargetType="TabItem">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="TabItem">
                                <Grid>
                                    <TabPanel  IsItemsHost="True"/>

                                </Grid>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </TabControl.ItemContainerStyle>

            <TabControl.Items>
                <TabItem Header="First" BorderBrush="#FFFF9700" Background="Red" Foreground="#FF003AFF" Margin="-2,-2,-2,0" Width="100" HorizontalContentAlignment="Stretch" Padding="6,2" UseLayoutRounding="False" VerticalContentAlignment="Stretch" BorderThickness="2" Cursor="None" IsSelected="True" RenderTransformOrigin="0.5,0.5">
                    <Grid>
                        <Button Content="Button" Height="40" Width="112"/>
                        <CheckBox Content="CheckBox" Margin="102,52,127,143" />
                    </Grid>
                </TabItem>
                <TabItem Header="Secand" BorderBrush="#FFD100FF" Background="#FF07EC50" Foreground="Red" BorderThickness="5">
                    <Grid/>
                </TabItem>
            </TabControl.Items>
        </TabControl>

ولی خط مربوط به تگ TabPanel ، ارور زیر را میده :

کد:
A panel with IsItemsHost="true" is not nested in an ItemsControl. Panel must be nested in ItemsControl to get and show items.

اما همین کد را مایکروسافت ، به عنوان تمپلیت SimpleTabControl نوشت و من هم روی tabcontrol ای پیاده سازی کردم ، هیچ مشکلی نداشت . کدش هم این بود :

کد:
            <!-- Simple TabControl
    This template uses Simple TabItem for each Tab. The TabItems are placed in the TabPanel
    Limitations : The Simple TabControl only allow the Tabs to be shown at the top of the Tab control. You can re-position the TabPanel to change this-->

            <Style x:Key="SimpleTabControl" TargetType="{x:Type TabControl}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type TabControl}">
                            <Grid KeyboardNavigation.TabNavigation="Local">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition Height="*"/>
                                </Grid.RowDefinitions>

                                <!-- TabPanel is a layout container which allows the TabItems to wrap and re-order when selected
                        The implementation knows to use this control because it is marked IsItemsHost = True -->
                                <TabPanel Grid.Row="0" Margin="0,0,4,-1" x:Name="HeaderPanel" Background="Transparent" IsItemsHost="True" Panel.ZIndex="1" KeyboardNavigation.TabIndex="1"/>

                                <Border Grid.Row="1" x:Name="Border" Background="{DynamicResource WindowBackgroundBrush}" BorderBrush="{DynamicResource SolidBorderBrush}" BorderThickness="1" CornerRadius="2" KeyboardNavigation.DirectionalNavigation="Contained" KeyboardNavigation.TabNavigation="Local" KeyboardNavigation.TabIndex="2">

                                    <!-- The implementation switches the content. This control must be named PART_SelectedContentHost -->
                                    <ContentPresenter Margin="4" x:Name="PART_SelectedContentHost" ContentSource="SelectedContent"/>

                                </Border>
                            </Grid>

                            <ControlTemplate.Triggers>
                                <Trigger Property="IsEnabled" Value="False">
                                    <Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/>
                                    <Setter Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" TargetName="Border"/>
                                </Trigger>
                            </ControlTemplate.Triggers>

                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

اما چند تا سئوال برام پیش اومد :
1) توی اون تگ TabPanel ، کد من که مثل همون کد مایکروسافت هست . پس چرا واسه ی من ارور میده و برای اون ارور نمیده؟
2) در کد مایکروسافت (کد دوم) ، هر چی توی کدش گشتم ، هیچ جا ندیدم که TabItem ها را به کنترل TabPanel اش اضافه کنه . یا جایی و در پروپرتی ای ، Binding انجام بده . اما وقتی این استایل اش را در کنترل TabControl ام اجرا کردم و resource دادم ، TabItem ها ام را شناخت و کار کرد . پس با کدوم قسمت از کدش ، کاری کرد که TabItem های داده شده به TabControl ، به TabPanel اش اضافه بشه؟
3) من چجوری میتونم TabItem هایی که به TabControl ام دادم را به TabPanel ام اضافه بشه؟ و همچنین این ارور را چجوری رفع کنم؟

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

the_king

مدیرکل انجمن
منظورتون گزینه ی شماره ی 2 ای که در پست قبلی گفتم ، هست؟
منظورم ساختن ControlTemplate برای TabItem ئه، اینکه کجا میسازیدش به استفاده خودتون بستگی داره.
کد:
    <Grid Background="LightGray">
        <Grid.Resources>
            <Style TargetType="TabItem">
                <Style.Setters>
                    <Setter Property="Width" Value="100"/>
                    <Setter Property="Height" Value="50"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="TabItem">
                                <Grid x:Name="Root">
                                    <Border x:Name="Border">
                                        <ContentPresenter x:Name="ContentSite" ContentSource="Header"/>
                                    </Border>
                                </Grid>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsSelected" Value="True">
                                        <Setter TargetName="Border" Property="Background" Value="White"></Setter>
                                        <Setter Property="Foreground" Value="DarkBlue"></Setter>
                                    </Trigger>
                                    <Trigger Property="IsSelected" Value="False">
                                        <Setter TargetName="Border" Property="Background" Value="DeepSkyBlue"></Setter>
                                        <Setter Property="Foreground" Value="White"></Setter>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style.Setters>
            </Style>
        </Grid.Resources>
        <TabControl TabStripPlacement="Right" Margin="50,50,50,50">
            <TabItem Header="TabItem">
                <Grid/>
            </TabItem>
            <TabItem Header="TabItem">
                <Grid/>
            </TabItem>
        </TabControl>
    </Grid>

کد:
    <Grid Background="LightGray">
        <TabControl TabStripPlacement="Right" Margin="50,50,50,50">
            <TabControl.ItemContainerStyle>
                <Style TargetType="TabItem">
                    <Style.Setters>
                        <Setter Property="Width" Value="100"/>
                        <Setter Property="Height" Value="50"/>
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="TabItem">
                                    <Grid x:Name="Root">
                                        <Border x:Name="Border">
                                            <ContentPresenter x:Name="ContentSite" ContentSource="Header"/>
                                        </Border>
                                    </Grid>
                                    <ControlTemplate.Triggers>
                                        <Trigger Property="IsSelected" Value="True">
                                            <Setter TargetName="Border" Property="Background" Value="White"></Setter>
                                            <Setter Property="Foreground" Value="DarkBlue"></Setter>
                                        </Trigger>
                                        <Trigger Property="IsSelected" Value="False">
                                            <Setter TargetName="Border" Property="Background" Value="DeepSkyBlue"></Setter>
                                            <Setter Property="Foreground" Value="White"></Setter>
                                        </Trigger>
                                    </ControlTemplate.Triggers>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style.Setters>
                </Style>
            </TabControl.ItemContainerStyle>
            <TabItem Header="TabItem">
                <Grid/>
            </TabItem>
            <TabItem Header="TabItem">
                <Grid/>
            </TabItem>
        </TabControl>
    </Grid>
اگه آره ، من پروپرتی Template (مربوط به TabItem) را مقدار دادم اما فقط همون آیتم را میتونم از نو بسازم.
برای شیء خاصی Style مقدار دهی نکنید، Style عمومی بسازید که برای هر TabItem ای قابل استفاده باشه.

اون قسمت پایین اش که Transparent هست را نمیتونم . برای این قسمتِ Transparent ، انگار پروپرتیِ TabControl.ItemContainerStyle را باید استایل بدم .
ظاهرش رو خودتون تعریف می کنید، طبعا هر چیزی که خودتون تعریف کنید می تونه اونطوری باشه که میخواهید.

این کار را انجام دادم (یعنی پروپرتیِ TabControl.ItemContainerStyle را استایل دادم) . و کدم هم ، کد زیر هست :
کد:
        <TabControl HorizontalAlignment="Left" Height="181" Margin="382,16,0,0" VerticalAlignment="Top" Width="400" Background="#FF939393" BorderThickness="2" RenderTransformOrigin="0.5,0.5" IsSynchronizedWithCurrentItem="False" BorderBrush="#FF8D8D8D" Foreground="Black" TabStripPlacement="Right">
            <TabControl.ItemContainerStyle >
                <Style TargetType="TabItem">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="TabItem">
                                <Grid>
                                    <TabPanel  IsItemsHost="True"/>

                                </Grid>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </TabControl.ItemContainerStyle>

            <TabControl.Items>
                <TabItem Header="First" BorderBrush="#FFFF9700" Background="Red" Foreground="#FF003AFF" Margin="-2,-2,-2,0" Width="100" HorizontalContentAlignment="Stretch" Padding="6,2" UseLayoutRounding="False" VerticalContentAlignment="Stretch" BorderThickness="2" Cursor="None" IsSelected="True" RenderTransformOrigin="0.5,0.5">
                    <Grid>
                        <Button Content="Button" Height="40" Width="112"/>
                        <CheckBox Content="CheckBox" Margin="102,52,127,143" />
                    </Grid>
                </TabItem>
                <TabItem Header="Secand" BorderBrush="#FFD100FF" Background="#FF07EC50" Foreground="Red" BorderThickness="5">
                    <Grid/>
                </TabItem>
            </TabControl.Items>
        </TabControl>

ولی خط مربوط به تگ TabPanel ، ارور زیر را میده :

کد:
A panel with IsItemsHost="true" is not nested in an ItemsControl. Panel must be nested in ItemsControl to get and show items.

اما همین کد را مایکروسافت ، به عنوان تمپلیت SimpleTabControl نوشت و من هم روی tabcontrol ای پیاده سازی کردم ، هیچ مشکلی نداشت .

اما چند تا سئوال برام پیش اومد :
1) توی اون تگ TabPanel ، کد من که مثل همون کد مایکروسافت هست . پس چرا واسه ی من ارور میده و برای اون ارور نمیده؟
چون ControlTemplate های TabControl و TabItem رو قاطی پاتی کردید. من در کد شما داخل ControlTemplate ئه TabItem یک توصیف TabPanel می بینم که IsItemsHost اش True ئه.
در کد مایکروسافت ببینید TabPanel کجا توصیف شده؟ در ControlTemplate ئه TabControl یا در ControlTemplate ئه TabItem؟

2) در کد مایکروسافت (کد دوم) ، هر چی توی کدش گشتم ، هیچ جا ندیدم که TabItem ها را به کنترل TabPanel اش اضافه کنه . یا جایی و در پروپرتی ای ، Binding انجام بده . اما وقتی این استایل اش را در کنترل TabControl ام اجرا کردم و resource دادم ، TabItem ها ام را شناخت و کار کرد . پس با کدوم قسمت از کدش ، کاری کرد که TabItem های داده شده به TabControl ، به TabPanel اش اضافه بشه؟
خیلی ساده. کد کلاسش، وقتی Panel ای مشخصه IsItemsHost رو True می کنه، IsItemsHostProperty به صاحبش که یک ItemsControl ئه سیگنال میده که این مقدار عوض شد.
اونم با یک متد OnIsItemsHostChanged ای که اجرا میشه ItemsHost اش رو تنظیم می کنه روی اون Panel و دیگه میدونه با کدوم Panel باید کار کنه و بهش دسترسی داره، هر وقت بخواد میتونه آیتم داخلش قرار بده.

3) من چجوری میتونم TabItem هایی که به TabControl ام دادم را به TabPanel ام اضافه بشه؟ و همچنین این ارور را چجوری رفع کنم؟
برای اضافه کردن آیتم ها کار خاصی نباید بکنید، کار کلاس همونه و اگه اختلالی در کارش ایجاد نکنید خودش انجامش میده.
صرفا اگه میخواهید برای TabControl ئه ControlTemplate بسازید باید طبق قالبی که در سایت مایکروسافت نمونه اش هست پیش برید.
کد های XAML رو اگه قاطی پاتی نکنید درست کار می کنند، فقط یک کمی دقت می خواد.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
منظورم ساختن ControlTemplate برای TabItem ئه، اینکه کجا میسازیدش به استفاده خودتون بستگی داره.

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

برای شیء خاصی Style مقدار دهی نکنید، Style عمومی بسازید که برای هر TabItem ای قابل استفاده باشه.

بله .
اما اگه برای پروپرتی Template ئه مربوط به TabItem (نه اینکه پروپرتی Template ئه مربوط به TabControl) را بهش تمپلیت بدیم ، فقط همون یک دونه از TabItem ای را که مشخص کرده بودیم را مشخص میکنه و به بقیه ی TabItem ها کاری نداره .

چون ControlTemplate های TabControl و TabItem رو قاطی پاتی کردید. من در کد شما داخل ControlTemplate ئه TabItem یک توصیف TabPanel می بینم که IsItemsHost اش True ئه.
در کد مایکروسافت ببینید TabPanel کجا توصیف شده؟ در ControlTemplate ئه TabControl یا در ControlTemplate ئه TabItem؟

بله . خیلی ممنون

خیلی ساده. کد کلاسش، وقتی Panel ای مشخصه IsItemsHost رو True می کنه، IsItemsHostProperty به صاحبش که یک ItemsControl ئه سیگنال میده که این مقدار عوض شد.
اونم با یک متد OnIsItemsHostChanged ای که اجرا میشه ItemsHost اش رو تنظیم می کنه روی اون Panel و دیگه میدونه با کدوم Panel باید کار کنه و بهش دسترسی داره، هر وقت بخواد میتونه آیتم داخلش قرار بده.

یه چیزهایی متوجه شدم ولی نه دقیق :green:

برای اضافه کردن آیتم ها کار خاصی نباید بکنید، کار کلاس همونه و اگه اختلالی در کارش ایجاد نکنید خودش انجامش میده.
صرفا اگه میخواهید برای TabControl ئه ControlTemplate بسازید باید طبق قالبی که در سایت مایکروسافت نمونه اش هست پیش برید.
کد های XAML رو اگه قاطی پاتی نکنید درست کار می کنند، فقط یک کمی دقت می خواد.

بله .
استاد ، این چیزهایی که میگم ، ببینین درسته؟ :

اول اینکه کنترل هایی که دارای آیتم هستند (مثل combobox و TabControl و ...) ، دارای بخشی بنام TabItem هستند . و پروپرتی ای بنام ItemContainerStyle دارند که میشه بهش استایل داد (و بنابراین Template هم میشه داد) که این استایل و تمپلیت ، استایل و شکل بخش آیتم ها را مشخص میکنه . در واقع ، وقتی به ItemContainerStyle ، استایل و تمپلیست میدیم ، اولا فقط در حیطه ی یک آیتم اِعمال میشه (یعنی این جور نیست که وقتی یه Grid ای در استایل و تمپلیتِ مربوط به ItemContainerStyle رسم میکنیم ، کلِ آیتم های موجود را شامل بشه و به اندازه ی کل آیتم های اون کنترل بشه . بلکه فقط به اندازه ی یک آیتم هست) و دوما ، استایل ای که دادیم ، استایلِ همه ی آیتم های موجود خواهد شد . یعنی همه ی آیتم ها ، اون استایل را برای خودشون رسم میکنن .

بنابراین چون در این پروپرتی ، فقط به اندازه ی هر آیتمِ اون کنترل میتونیم رسم انجام بدیم ، اگه بخوایم بیشتر از فضای اون آیتم ، رسم ای انجام بدیم ، توسط این پروپرتی ، نمیتونیم و باید برای کل اون کنترل (یعنی توسط پروپرتیِ Template یا پروپرتیِ Style اون کنترل) رسم انجام بدیم .
مثلا مثل همین کاری که میخواستم بدم و در بخشِ پایینِ آیتم های TabControl (پشت زمینه ی آیتم هاش) ، چیزی رسم کنم . چون در محدوده ی بیرونِ از آیتم هاست ، بنابراین توسط پروپرتیِ ItemContainerStyle نمیشه و باید توسط پروپرتیِ Template یا پروپرتیِ Style مربوط به TabControl ، این کار را انجام بدم .
یا اگه بخوایم دورِ کلِ آیتم های این کنترل ها (کنترل TabControl یا combobox) ، یه border رسم کنیم ، باز هم توسط پروپرتیِ ItemContainerStyle نمیشه و باید توسط پروپرتیِ Template یا پروپرتیِ Style مربوط به این کنترل ها ، این کار را انجام بدیم .

دوم اینکه پروپرتیِ Template ای که در کنترل ها هست ، باعث میشه کلِ اون کنترل را از نو رسم کنیم . اما همونطور که در نکته ی اول گفتم ، پروپرتیِ ItemContainerStyle ئه مربوط به اون کنترل ، باعث میشه استایل و تمپلیت هایی که فقط مربوط به بخش آیتم های اون کنترل هستند را رسم کنیم .

سوم اینکه در کنترل TabControl ، هر TabItem ، پروپرتی ای بنام Template و Style داره که بصورت اختصاصی میتونیم فقط استایل های مربوط به همون TabItem را تغییر بدیم (برخلاف پروپرتیِ ItemContainerStyle ئه TabControl که باهاش همه ی TabItem را میتونیم با هم به یک شکل ، استایل بدیم) .
بنابراین پروپرتی Template و Style ئه مربوط به TabItem ها ، زمانی به درد میخوره که بخوایم استایل یه آیتم خاص را تغییر بدیم . مثلا یه آیتم ، اندازه ی پیش فرض اش نسبت به بقیه ی آیتم ها بزرگ تر باشه یا هر تغییر دیگه ای .

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

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

چیزی که میخواستم ، این بود استاد (حالا Background بوردر را ندادم) :

کد:
            <!-- Simple TabControl
    This template uses Simple TabItem for each Tab. The TabItems are placed in the TabPanel
    Limitations : The Simple TabControl only allow the Tabs to be shown at the top of the Tab control. You can re-position the TabPanel to change this-->

            <Style x:Key="SimpleTabControl" TargetType="{x:Type TabControl}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type TabControl}">
                            <Grid KeyboardNavigation.TabNavigation="Local">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition Height="*"/>
                                </Grid.RowDefinitions>

                                <!-- TabPanel is a layout container which allows the TabItems to wrap and re-order when selected
                        The implementation knows to use this control because it is marked IsItemsHost = True -->
                                <Border Grid.Row="0" BorderBrush="Red" BorderThickness="1"/>
                                <TabPanel Grid.Row="0" Margin="0,0,4,-1" x:Name="HeaderPanel" Background="Transparent" IsItemsHost="True" Panel.ZIndex="1" KeyboardNavigation.TabIndex="1"/>

                                <Border Grid.Row="1" x:Name="Border" Background="{DynamicResource WindowBackgroundBrush}" BorderBrush="{DynamicResource SolidBorderBrush}" BorderThickness="1" CornerRadius="2" KeyboardNavigation.DirectionalNavigation="Contained" KeyboardNavigation.TabNavigation="Local" KeyboardNavigation.TabIndex="2">

                                    <!-- The implementation switches the content. This control must be named PART_SelectedContentHost -->
                                    <ContentPresenter Margin="4" x:Name="PART_SelectedContentHost" ContentSource="SelectedContent"/>

                                </Border>
                            </Grid>

                            <ControlTemplate.Triggers>
                                <Trigger Property="IsEnabled" Value="False">
                                    <Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/>
                                    <Setter Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" TargetName="Border"/>
                                </Trigger>
                            </ControlTemplate.Triggers>

                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

بعد استاد ، طبق کد زیر :

کد:
            <Style x:Key="SimpleTabItem"  TargetType="{x:Type TabItem}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type TabItem}">
                            <Grid>
                                <Border Margin="0,0,-4,0" x:Name="Border" Background="{DynamicResource LightBrush}" BorderBrush="{DynamicResource SolidBorderBrush}" BorderThickness="2,2,2,2" CornerRadius="2,12,0,0">
                                    <ContentPresenter  Margin="10,2" ContentSource="Header"/>
                                </Border>
                            </Grid>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsSelected" Value="True">
                                    <Setter Property="Panel.ZIndex" Value="100"/>
                                    <Setter Property="Background" Value="{DynamicResource WindowBackgroundBrush}" TargetName="Border"/>
                                    <Setter Property="BorderThickness" Value="1,1,1,0" TargetName="Border"/>
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="False">
                                    <Setter Property="Background" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border"/>
                                    <Setter Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" TargetName="Border"/>
                                    <Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

اولا ContentPresenter ، لازم نیست که فقط برای کنترل هایی از نوع ContentControl بکار برده بشه . چون ContentPresenter که در کد بالا (برای Border) اومد ، اون Border که از نوع ContentControl نیست .
دوما ، پروپرتی ContentSource مربوط به ContentControl ، یعنی اینکه نام پروپرتی ای را بهش بدیم که محتوای اون را نشون بده؟ اینه قضیه اش؟
اگه اینه ، پس در کد اول که ContentSource="SelectedContent" هست ، اون SelectedContent چیه و از کجا آورد؟
اگه این نیست ، پس در کد دوم که ContentSource="Header" هست ، منظورش همون Header ئه مربوط به هر TabItem هه دیگه ؟ (چون نوع ControlTemplate مون ، TabItem هست دیگه) .

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

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

بالا