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

SajjadKhati

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

XML:
        <ComboBox x:Name="myComboBox" Style="{StaticResource SimpleComboBox}" Height="28" Margin="10,592,0,0"  VerticalAlignment="Top" Width="201" SelectedIndex="0" HorizontalAlignment="Left" Background="#FF505050" BorderBrush="White" Foreground="White">
            <System:String>salam</System:String>
            <System:String>khobi?</System:String>
            <System:String>chetori?</System:String>
            <System:String>kojaee?</System:String>
        </ComboBox>

همون قضیه ی کمبوباکس قبلی هه حالا ویرایشاتی انجام دادم .
وقتی Foreground ئه کمبوباکسِ myComboBox (کمبوباکس بالا) را تغییر میدم ، رنگ آیتم های کمبوباکس هم تغییر میکنه (یعنی رنگ اون هایی که در پنجره ی popup لیست شدن هم تغییر میکنه . منظورم رنگ بخش ToggleButton یا TextBox ئه کمبوباکس نیست) .
در صورتی که من هر جا را میبینم ، کدی ننوشتم که با تغییر Foreground ئه کمبوباکسِ myComboBox ، رنگ آیتم ها (رنگ آیتم های درون popup) هم تغییر کنه . کدوم بخش از کد باعث میشه که این اتفاق بیافته؟

البته من هم قصدم همین هست که رنگ آیتم های popup هم همین جوری به Foreground اش متصل بشه اما نمیدونم کدوم بخش از کد ، باعث این اتفاق میشه .

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

ممنون استاد .
 

پیوست ها

  • combobox template.txt
    9.3 کیلوبایت · بازدیدها: 1

the_king

مدیرکل انجمن
سلامی مجدد
استاد ، این فایلی را که پیوست میکنم ، در Resource نوشتم که حاوی تمپلیت هه.
بعد هم این کمبوباکس را تعریف کردم که از اون تمپلیت استفاده میکنه :

XML:
        <ComboBox x:Name="myComboBox" Style="{StaticResource SimpleComboBox}" Height="28" Margin="10,592,0,0"  VerticalAlignment="Top" Width="201" SelectedIndex="0" HorizontalAlignment="Left" Background="#FF505050" BorderBrush="White" Foreground="White">
            <System:String>salam</System:String>
            <System:String>khobi?</System:String>
            <System:String>chetori?</System:String>
            <System:String>kojaee?</System:String>
        </ComboBox>

همون قضیه ی کمبوباکس قبلی هه حالا ویرایشاتی انجام دادم .
وقتی Foreground ئه کمبوباکسِ myComboBox (کمبوباکس بالا) را تغییر میدم ، رنگ آیتم های کمبوباکس هم تغییر میکنه (یعنی رنگ اون هایی که در پنجره ی popup لیست شدن هم تغییر میکنه . منظورم رنگ بخش ToggleButton یا TextBox ئه کمبوباکس نیست) .
در صورتی که من هر جا را میبینم ، کدی ننوشتم که با تغییر Foreground ئه کمبوباکسِ myComboBox ، رنگ آیتم ها (رنگ آیتم های درون popup) هم تغییر کنه . کدوم بخش از کد باعث میشه که این اتفاق بیافته؟

البته من هم قصدم همین هست که رنگ آیتم های popup هم همین جوری به Foreground اش متصل بشه اما نمیدونم کدوم بخش از کد ، باعث این اتفاق میشه .
مربوط به <ItemsPresenter/> ئه، اگر TextBlock.Foreground اش رو تغییر ندهید از Foreground کنترل استفاده میکنه.
<ItemsPresenter TextBlock.Foreground="Yellow" />

همچنین اینکه استاد وقتی روی کمبوباکس کلیک میکنم ، بین بخش ToggleButton و بخش popup ، یه فاصله ی حدود 5 پیکسل وجود داره که باز هم نمیدونم کدوم بخش از کد باعث ایجاد این فاصله شد و هر چی میگردم ، کدی که مربوط به این قضیه باشه را پیدا نمیکنم . کدوم بخش از کد باعث این قضیه شد و بخوام فاصله بین شون نباشه ، چی کار کنم؟
به DropDownBorder ئه Margin دادید، حذفش کنید.
XML:
<Setter Property="Margin" Value="0,2,0,0" TargetName="DropDownBorder"/>
 

SajjadKhati

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

XML:
            <Style x:Key="ComboboxItemStyle" TargetType="{x:Type ComboBoxItem}">
                <Style.Setters>
                    <Setter Property="Template">
                        <Setter.Value>

                            <ControlTemplate TargetType="{x:Type ComboBoxItem}">
                                <Grid Background="Transparent">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="20"/>
                                        <ColumnDefinition Width="Auto"/>
                                    </Grid.ColumnDefinitions>

                                    <Path x:Name="tickPath" Grid.Column="0" Visibility="Hidden"  Stroke="{StaticResource combItem_MouseEnterColor}" StrokeThickness="1" Fill="{StaticResource combItem_MouseEnterColor}" StrokeStartLineCap="Triangle" StrokeEndLineCap="Triangle" Data="{Binding Source={StaticResource checkboxTickPath}, Path=Data }"/>
                                    <Border Grid.Column="1">
                                        <ContentPresenter/>
                                    </Border>
                                </Grid>
                            </ControlTemplate>
                            
                        </Setter.Value>
                    </Setter>
                </Style.Setters>
            </Style>

که این استایلِ ComboboxItemStyle را به پروپرتیِ ItemContainerStyle از شی ComboBox دادم .(این کمبوباکس ، همون کمبوباکس با نام myComboBox که در 2 پست بالا کدش را دادم ، هست).
بقیه ی کدها هم همونی هه که در 2 پستِ بالاتر (پست 361) دادم (همراه فایل پیوستی اش) مگر کد زیر که در ریسورس گذاشتم :

XML:
<Path x:Key="checkboxTickPath"  Data="M1,7 Q3,7 5,9 Q8,4 12,2 M1,7 Q3.2,7.2 5,11 Q8.2,4.2 12,2"/>
کد:

استاد ، میخوام هر آیتمی از این کمبوباکس که انتخاب بود (نه اینکه کاربر با موس روش بره . یعنی همون هر مقداری که پروپرتیِ SelectedIndex ئه کمبوباکس بود) ، اون آیتم از کمبوباکس ، اون شکل (Path) با نام tickPath در کد بالا که دادم ، (فقط برای اون آیتم) ، پروپرتیِ Visibility اش مقدار Visible بگیره و نمایش داده بشه .

اگه افترافکت را دارین ، مثل کمبوباکس هایی که در تنظیمات Preference ئه افترافکت هست که آیتمی که انتخاب هست (نه اینکه کاربر موس را روی اون آیتم میبره) ، یه تیک کنار اون آیتم داره و رنگ نوشته اش آبی هه . یا همچنین یه کم در PowerDVD .

اما نمیدونم چجوری میشه . نمیدونم اصلا توی xaml امکان پذیره یا این بخش را باید توی سی شارپ نوشت؟
از لحاظ رویداد ، توی رویداد SelectionChanged میشه این کد را نوشت . اما در xaml نمیدونم چی باید بنویسم که فقط روی اون آیتمی که پروپرتیِ SelectedIndex اش مد نظرمه ، فقط روی اون آیتم عملیات انجام بده (و Visibility ئه tickPath) را فعال کنم؟

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

استاد ، مگه xaml در wpf ، مفسر نداره؟
من آخر فرق کمپایلر و مفسر را متوجه نشدم .
مفسرها مگه اونهایی نبودن که صرفا خط به خط ، کدها را میخوندن و تفسیر میکردن؟

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

the_king

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

XML:
            <Style x:Key="ComboboxItemStyle" TargetType="{x:Type ComboBoxItem}">
                <Style.Setters>
                    <Setter Property="Template">
                        <Setter.Value>

                            <ControlTemplate TargetType="{x:Type ComboBoxItem}">
                                <Grid Background="Transparent">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="20"/>
                                        <ColumnDefinition Width="Auto"/>
                                    </Grid.ColumnDefinitions>

                                    <Path x:Name="tickPath" Grid.Column="0" Visibility="Hidden"  Stroke="{StaticResource combItem_MouseEnterColor}" StrokeThickness="1" Fill="{StaticResource combItem_MouseEnterColor}" StrokeStartLineCap="Triangle" StrokeEndLineCap="Triangle" Data="{Binding Source={StaticResource checkboxTickPath}, Path=Data }"/>
                                    <Border Grid.Column="1">
                                        <ContentPresenter/>
                                    </Border>
                                </Grid>
                            </ControlTemplate>
                           
                        </Setter.Value>
                    </Setter>
                </Style.Setters>
            </Style>

که این استایلِ ComboboxItemStyle را به پروپرتیِ ItemContainerStyle از شی ComboBox دادم .(این کمبوباکس ، همون کمبوباکس با نام myComboBox که در 2 پست بالا کدش را دادم ، هست).
بقیه ی کدها هم همونی هه که در 2 پستِ بالاتر (پست 361) دادم (همراه فایل پیوستی اش) مگر کد زیر که در ریسورس گذاشتم :

XML:
<Path x:Key="checkboxTickPath"  Data="M1,7 Q3,7 5,9 Q8,4 12,2 M1,7 Q3.2,7.2 5,11 Q8.2,4.2 12,2"/>
کد:

استاد ، میخوام هر آیتمی از این کمبوباکس که انتخاب بود (نه اینکه کاربر با موس روش بره . یعنی همون هر مقداری که پروپرتیِ SelectedIndex ئه کمبوباکس بود) ، اون آیتم از کمبوباکس ، اون شکل (Path) با نام tickPath در کد بالا که دادم ، (فقط برای اون آیتم) ، پروپرتیِ Visibility اش مقدار Visible بگیره و نمایش داده بشه .

اگه افترافکت را دارین ، مثل کمبوباکس هایی که در تنظیمات Preference ئه افترافکت هست که آیتمی که انتخاب هست (نه اینکه کاربر موس را روی اون آیتم میبره) ، یه تیک کنار اون آیتم داره و رنگ نوشته اش آبی هه . یا همچنین یه کم در PowerDVD .

اما نمیدونم چجوری میشه . نمیدونم اصلا توی xaml امکان پذیره یا این بخش را باید توی سی شارپ نوشت؟
از لحاظ رویداد ، توی رویداد SelectionChanged میشه این کد را نوشت . اما در xaml نمیدونم چی باید بنویسم که فقط روی اون آیتمی که پروپرتیِ SelectedIndex اش مد نظرمه ، فقط روی اون آیتم عملیات انجام بده (و Visibility ئه tickPath) را فعال کنم؟
کار پیچیده ای نیست، به ControlTemplate اون ComboboxItemStyle یک Trigger اضافه می کنید.
XML:
                               <ControlTemplate.Triggers>
                                    <Trigger Property="IsSelected" Value="true">
                                        <Setter TargetName="tickPath" Property="Visibility" Value="Visible"/>
                                    </Trigger>
                                </ControlTemplate.Triggers>

استاد ، مگه xaml در wpf ، مفسر نداره؟
من آخر فرق کمپایلر و مفسر را متوجه نشدم .
مفسرها مگه اونهایی نبودن که صرفا خط به خط ، کدها را میخوندن و تفسیر میکردن؟

الان اگه resource ها را در خطِ پایین تر از اون جایی که میخوام فراخونی شون کنم ، تعریف کنم ، موقع اجرا ، ارور میده . یعنی خط به خط عملیاتش انجام میشه دیگه . درست نیست؟
در اینکه خط به خط اجرا میشه اختلاف نظری نداریم اما خط به خط اجرا شدن ویژگی اختصاصی اجرای مفسری که نیست، کد زبان ماشین هم خط به خط اجرا میشه. موقعیت خطا در موقع اجرا به ترتیب اجرای کد بستگی داره، ربطی به این نداره که کدی که داره اجرا میشه کد زبان سطح بالا است که مفسری اجرا میشه یا کد زبان میانی یا کد زبان ماشین که قبلا کامپایل شده. این دو تا عبارت رو در گوگل جستجو کنید ببینید برای هر کدوم چند تا نتیجه جستجو میاره :
"site:docs.microsoft.com "xaml interpreter
"site:docs.microsoft.com "xaml compiler
برای xaml compiler چند هزار مورد ولی برای xaml interpreter صرفا یک مورد نتیجه میاره که اونم داخل متنش xaml interpreter نیست و صرفا بخاطر یک interpreted در متن نشونش میده که ربطی به XAML نداره.
در مورد BAML یا Binary Application Markup Language هم که توسط کامپایلر XAML تولید میشه قبلا صحبت کرده بودیم، اگر مفسری بود که BAML ای تولید نمی شد.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
کار پیچیده ای نیست، به ControlTemplate اون ComboboxItemStyle یک Trigger اضافه می کنید.
XML:
                               <ControlTemplate.Triggers>
                                    <Trigger Property="IsSelected" Value="true">
                                        <Setter TargetName="tickPath" Property="Visibility" Value="Visible"/>
                                    </Trigger>
                                </ControlTemplate.Triggers>

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

بعد اینکه استاد ، الان مثلا در کد بالا ، گفته شد اگه پروپرتیِ IsSelected ئه شیِ ComboBoxItem مون مقدارش true شد ، مقدار پروپرتیِ Visibility ئه شیِ tickPath مون را Visible کن . اما هیچ جا گفته نشد کدوم آیتم (همون پروپرتیِ SelectedIndex) از شیِ ComboBoxItem را براش این عملیات را انجام بده و براش مقدار پروپرتیِ Visibility ئه شیِ tickPath را Visible کن . پس از کجا متوجه میشه که برای کدوم آیتم باید این کار را کنه؟

در اینکه خط به خط اجرا میشه اختلاف نظری نداریم اما خط به خط اجرا شدن ویژگی اختصاصی اجرای مفسری که نیست، کد زبان ماشین هم خط به خط اجرا میشه. موقعیت خطا در موقع اجرا به ترتیب اجرای کد بستگی داره، ربطی به این نداره که کدی که داره اجرا میشه کد زبان سطح بالا است که مفسری اجرا میشه یا کد زبان میانی یا کد زبان ماشین که قبلا کامپایل شده. این دو تا عبارت رو در گوگل جستجو کنید ببینید برای هر کدوم چند تا نتیجه جستجو میاره :
"site:docs.microsoft.com "xaml interpreter
"site:docs.microsoft.com "xaml compiler
برای xaml compiler چند هزار مورد ولی برای xaml interpreter صرفا یک مورد نتیجه میاره که اونم داخل متنش xaml interpreter نیست و صرفا بخاطر یک interpreted در متن نشونش میده که ربطی به XAML نداره.
در مورد BAML یا Binary Application Markup Language هم که توسط کامپایلر XAML تولید میشه قبلا صحبت کرده بودیم، اگر مفسری بود که BAML ای تولید نمی شد.

ممنون .
پس xaml در wpf ، مفسر نداره و کمپایلر داره .
هر چند فرق شون را نمیدونم .
 

the_king

مدیرکل انجمن
خیلی ممنون استاد .
استاد ، پس برای قضیه ی تریگر انگار چیزی که دستم اومد اینه که اول به پروپرتی ها(یی که معمولا با Is شروع میشن) باید توجه ویژه کنیم (و ببینیم همچین پروپرتی هایی وجود دارن یا نه . البته فقط محدود به این پروپرتی نیست) وگرنه از EventTrigger استفاده کنیم وگرنه هم که سرآخر از رویدادهای خود سی شارپ استفاده کنیم . روند کلی اش درسته؟
با دیدگاه تون موافق نیستم، شروع به کد نویسی برای کنترل هایی کرده اید که شناختی ازشون نداشتید، برای همین نمیدونید که چه مشخصی ای برای چه کاری است. اگه پیش از شروع کد نویسی XAML به کنترل های WPF و اجزاء و مشخصات شون توجه کرده باشید دیگه نیازی نیست برای حل مشکل دنبال الگویی برای پیدا کردن مشخصه مربوطه بگردید.

بعد اینکه استاد ، الان مثلا در کد بالا ، گفته شد اگه پروپرتیِ IsSelected ئه شیِ ComboBoxItem مون مقدارش true شد ، مقدار پروپرتیِ Visibility ئه شیِ tickPath مون را Visible کن . اما هیچ جا گفته نشد کدوم آیتم (همون پروپرتیِ SelectedIndex) از شیِ ComboBoxItem را براش این عملیات را انجام بده و براش مقدار پروپرتیِ Visibility ئه شیِ tickPath را Visible کن . پس از کجا متوجه میشه که برای کدوم آیتم باید این کار را کنه؟
خیلی واضح ئه، یک مجموعه آیتم دارید، داخلش چهار تا آیتم ئه، وقتی هیچکدوم انتخاب نشده IsSelected هر کدوم از آیتم ها false ئه.
حالا وقتی یک آیتم انتخاب میشه، چه با مقدار دهی SelectedIndex یا با کلیک ماوس یا ... برای یکی از آیتم ها که الان انتخاب شده IsSelected مقدار true میگیره. Trigger رو هم بر اساس تغییر این مقدار IsSelected نوشته ایم. طبعا اون Trigger هم برای آیتمی فعال میشه که شرط Trigger ئه true شده، برای آیتمی که انتخاب نشده که IsSelected مقدار true نداره که Trigger برایش عمل کنه. وقتی هم یک آیتمی از حالت انتخاب درمیاد IsSelected اش false میشه و تاثیری که Trigger رویش گذاشته بود باطل میشه.

پس xaml در wpf ، مفسر نداره و کمپایلر داره .
هر چند فرق شون را نمیدونم .
همه مون چیز های زیادی هست که نمی دونیم، ولی بهتره از اصطلاحاتی استفاده کنیم که به معنی شون تسلط داریم.
 

SajjadKhati

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


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

XML:
            <Style x:Key="SimpleComboBox" TargetType="{x:Type ComboBox}">
                <Setter Property="SnapsToDevicePixels" Value="False"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ComboBox}">
                            <Grid>
                                <!--Template="{DynamicResource ComboBoxTextBox}"-->

                                <!--The ToggleButton is databound to the ComboBox itself to toggle IsDropDownOpen-->
                                <ToggleButton x:Name="ToggleButton" Template="{DynamicResource ComboBoxToggleButton}" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" Foreground="{TemplateBinding Foreground}" Focusable="False" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press"/>
                                <ContentPresenter  x:Name="ContentSite" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="Center"  Margin="6,-2,20,0" IsHitTestVisible="False" TextBlock.Foreground="{TemplateBinding Foreground}" Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"/>

                                <!--The TextBox must be named PART_EditableTextBox or ComboBox will not recognize it-->
                                <TextBox x:Name="PART_EditableTextBox" Template="{DynamicResource TextBoxOfComboBoxTemplate}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="0,0,20,0" Focusable="True" Background= "{DynamicResource TextBoxOfComboBoxBackground}" Foreground="{TemplateBinding Foreground}" Visibility="Hidden" IsReadOnly="{TemplateBinding IsReadOnly}" BorderBrush="{TemplateBinding BorderBrush}"/>
                                <!--The Popup shows the list of items in the ComboBox. IsOpen is databound to IsDropDownOpen which is toggled via the ComboBoxToggleButton-->
                                <Popup x:Name="PART_Popup" IsOpen="{TemplateBinding IsDropDownOpen}" Placement="Bottom" Focusable="False" AllowsTransparency="True" PopupAnimation="Slide" MaxHeight="{TemplateBinding MaxHeight}" MaxWidth="{TemplateBinding MaxWidth}" MinWidth="{TemplateBinding ActualWidth}">
                                    <Grid x:Name="DropDown" SnapsToDevicePixels="True">
                                        <Border x:Name="DropDownBorder" Background="{DynamicResource comb_Pop_Fill_Brush}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1"/>
                                        <ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" CanContentScroll="True">

                                            <ItemsPresenter HorizontalAlignment="Right" />

                                        </ScrollViewer>
                                    </Grid>
                                </Popup>
                            </Grid>
                            <ControlTemplate.Triggers>
                                <!--This forces the DropDown to have a minimum size if it is empty-->
                                <Trigger Property="HasItems" Value="false">
                                    <Setter Property="MinHeight" Value="40" TargetName="DropDownBorder"/>
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="false">
                                    <Setter TargetName="PART_EditableTextBox" Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/>
                                    <Setter TargetName="PART_EditableTextBox" Property="Background" Value="{DynamicResource  DisabledBackgroundBrush}"/>
                                    <Setter  TargetName="PART_EditableTextBox" Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" />
                                </Trigger>
                                <Trigger Property="IsGrouping" Value="true">
                                    <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                                </Trigger>
                                <Trigger Property="AllowsTransparency" SourceName="PART_Popup" Value="true">
                                    <Setter Property="CornerRadius" Value="4" TargetName="DropDownBorder"/>
                                </Trigger>
                                <Trigger Property="IsEditable" Value="true">
                                    <Setter Property="IsTabStop" Value="false"/>
                                    <Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible"/>
                                    <Setter TargetName="ContentSite" Property="Visibility" Value="Hidden"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

پروپرتیِ HorizontalAlignment ئه ItemsPresenter رو که Right میکنم ، متن ها به سمت راست میان اما مشکلش اینه که کلا آیتم ها محدود میشن . یعنی وقتی موس را روی آیتم ها میبرم ، border اش (که آبی رنگ هه) محدود به بخش نوشته (با 20 پیکسل هم بهش مربوط به رسمِ path و اون تیک) میشه . اما من میخوام وقتی راست چین میکنم ، اون border تا آخر بره و فقط متن هاش به سمت راست بیان .
متوجه ی منظورم شدین؟
اگه آره ، چی کار باید کنم تا زمان راست چین کردن ، اون border تا آخر رسم بشه (متن ها که راست چین هستن) .
ادامه ی کدها هم :

XML:
            <Style x:Key="ComboboxItemStyle" TargetType="{x:Type ComboBoxItem}">
                <Style.Setters>
                    <Setter Property="Template">
                        <Setter.Value>

                            <ControlTemplate TargetType="{x:Type ComboBoxItem}">
                                <Border Name="combItemBorder" Background="Transparent">
                                    <Grid>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="20"/>
                                            <ColumnDefinition Width="Auto"/>
                                        </Grid.ColumnDefinitions>

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

                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsSelected" Value="True">
                                        <Setter TargetName="tickPath" Property="Visibility" Value="Visible"/>
                                        <Setter TargetName="combItemPresenter" Property="TextBlock.Foreground" Value="{StaticResource combItem_MouseEnterColor}"/>
                                    </Trigger>
                                    <Trigger Property="IsHighlighted" Value="True">
                                        <Setter TargetName="combItemBorder" Property="BorderThickness" Value="1"/>
                                        <Setter TargetName="combItemBorder" Property="BorderBrush" Value="{StaticResource combItem_MouseEnterColor}"/>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                         
                        </Setter.Value>
                    </Setter>
                </Style.Setters>
            </Style>
مقدار پروپرتیِ HorizontalContentAlignment ئه کمبوباکس ، Right باشه .
بقیه ی کدها هم همچنان همونی اند که در پست 361 دادم (فایل ضمیمه) .

بعد اینکه روی هر آیتمی که موس روش میره و Highlighte میشه ، margin و posation ئه متنِ اون آیتم ، به اندازه ای که مقدار پروپرتیِ BorderThickness ئه combItemBorder را مشخص کردیم (که در این مثال مقدارش 1 هست) ، جلوتر میره . راه ساده ای هست که این جوری نشه یا با ساخت یه تمپلیت حل میشه؟ یا اصلا با ساخت تمپلیت برای اون Border هم حل نمیشه؟

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

the_king

مدیرکل انجمن
آها خیلی ممنون استاد .
یعنی این ComboBoxItem ، برای هر آیتم شه . درسته؟
یعنی برای اون مقدار salam ، یه شی ای از ComboBoxItem هست و برای اون مقدار khobi ، یه مقدار دیگه از ComboBoxItem هست و به ازای هر یک
از ایم مقادیر هم یه شکل مجزا رسم میشه . هر کدوم از این ComboBoxItem ها هم مشخص هست که پروپرتی های متفاوتی میتونن داشته باشن .


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

XML:
            <Style x:Key="SimpleComboBox" TargetType="{x:Type ComboBox}">
                <Setter Property="SnapsToDevicePixels" Value="False"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ComboBox}">
                            <Grid>
                                <!--Template="{DynamicResource ComboBoxTextBox}"-->

                                <!--The ToggleButton is databound to the ComboBox itself to toggle IsDropDownOpen-->
                                <ToggleButton x:Name="ToggleButton" Template="{DynamicResource ComboBoxToggleButton}" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" Foreground="{TemplateBinding Foreground}" Focusable="False" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press"/>
                                <ContentPresenter  x:Name="ContentSite" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="Center"  Margin="6,-2,20,0" IsHitTestVisible="False" TextBlock.Foreground="{TemplateBinding Foreground}" Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"/>

                                <!--The TextBox must be named PART_EditableTextBox or ComboBox will not recognize it-->
                                <TextBox x:Name="PART_EditableTextBox" Template="{DynamicResource TextBoxOfComboBoxTemplate}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="0,0,20,0" Focusable="True" Background= "{DynamicResource TextBoxOfComboBoxBackground}" Foreground="{TemplateBinding Foreground}" Visibility="Hidden" IsReadOnly="{TemplateBinding IsReadOnly}" BorderBrush="{TemplateBinding BorderBrush}"/>
                                <!--The Popup shows the list of items in the ComboBox. IsOpen is databound to IsDropDownOpen which is toggled via the ComboBoxToggleButton-->
                                <Popup x:Name="PART_Popup" IsOpen="{TemplateBinding IsDropDownOpen}" Placement="Bottom" Focusable="False" AllowsTransparency="True" PopupAnimation="Slide" MaxHeight="{TemplateBinding MaxHeight}" MaxWidth="{TemplateBinding MaxWidth}" MinWidth="{TemplateBinding ActualWidth}">
                                    <Grid x:Name="DropDown" SnapsToDevicePixels="True">
                                        <Border x:Name="DropDownBorder" Background="{DynamicResource comb_Pop_Fill_Brush}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1"/>
                                        <ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" CanContentScroll="True">

                                            <ItemsPresenter HorizontalAlignment="Right" />

                                        </ScrollViewer>
                                    </Grid>
                                </Popup>
                            </Grid>
                            <ControlTemplate.Triggers>
                                <!--This forces the DropDown to have a minimum size if it is empty-->
                                <Trigger Property="HasItems" Value="false">
                                    <Setter Property="MinHeight" Value="40" TargetName="DropDownBorder"/>
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="false">
                                    <Setter TargetName="PART_EditableTextBox" Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/>
                                    <Setter TargetName="PART_EditableTextBox" Property="Background" Value="{DynamicResource  DisabledBackgroundBrush}"/>
                                    <Setter  TargetName="PART_EditableTextBox" Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" />
                                </Trigger>
                                <Trigger Property="IsGrouping" Value="true">
                                    <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                                </Trigger>
                                <Trigger Property="AllowsTransparency" SourceName="PART_Popup" Value="true">
                                    <Setter Property="CornerRadius" Value="4" TargetName="DropDownBorder"/>
                                </Trigger>
                                <Trigger Property="IsEditable" Value="true">
                                    <Setter Property="IsTabStop" Value="false"/>
                                    <Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible"/>
                                    <Setter TargetName="ContentSite" Property="Visibility" Value="Hidden"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

پروپرتیِ HorizontalAlignment ئه ItemsPresenter رو که Right میکنم ، متن ها به سمت راست میان اما مشکلش اینه که کلا آیتم ها محدود میشن . یعنی وقتی موس را روی آیتم ها میبرم ، border اش (که آبی رنگ هه) محدود به بخش نوشته (با 20 پیکسل هم بهش مربوط به رسمِ path و اون تیک) میشه . اما من میخوام وقتی راست چین میکنم ، اون border تا آخر بره و فقط متن هاش به سمت راست بیان .
متوجه ی منظورم شدین؟
اگه آره ، چی کار باید کنم تا زمان راست چین کردن ، اون border تا آخر رسم بشه (متن ها که راست چین هستن) .
به ItemsPresenter کاری نداشته باشید، اون باید شامل همه آیتم ها و path و Border ها بشه. وقتی قراره ItemsPresenter کل فضا رو پوشش بده، معنی نداره که "HorizontalAlignment="Right بشه. هر کاری که می کنید باید در ContentPresenter اون ComboBoxItem باشه که متن آیتم رو نمایش میده.
اشکال کار اینه که شما ستون دوم رو به اندازه طول متن میسازید، نه به اندازه کل فضایی که هست.
شما نوشته اید "ColumnDefinition Width="Auto در حالی که منظورتون "*"=ColumnDefinition Width بوده تا کل فضا رو پوشش بده، نه اینکه به اندازه طول متن ContentPresenter بشه.
وقتی طول ColumnDefinition رو درست مقدار دهی کردید می توانید با اضافه کردن "TextBlock.TextAlignment="Right به اون ContentPresenter متن رو به سمت راست بیارید.

بعد اینکه روی هر آیتمی که موس روش میره و Highlighte میشه ، margin و posation ئه متنِ اون آیتم ، به اندازه ای که مقدار پروپرتیِ BorderThickness ئه combItemBorder را مشخص کردیم (که در این مثال مقدارش 1 هست) ، جلوتر میره . راه ساده ای هست که این جوری نشه یا با ساخت یه تمپلیت حل میشه؟ یا اصلا با ساخت تمپلیت برای اون Border هم حل نمیشه؟
BorderThickness رو در Setter قرار ندهید، اجازه بدهید که همیشه BorderThickness ئه 1 باشه. یعنی چه IsHighlighted مقدار true داشته باشه و چه false باشه BorderThickness برابر 1 باشه، گر چه وقتی نمی خواهید دیده بشه BorderBrush اش Transparent باشه.
اینطوری فضای لازم برای اون خط حفظ میشه و دیگه جلوتر نمیره.
فقط BorderBrush رو در Setter تغییر بدهید تا آشکار و مخفی شدن صرفا با تغییر رنگ باشه.
XML:
<Border Name="combItemBorder" Background="Transparent" BorderThickness="1" BorderBrush="Transparent">
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
به ItemsPresenter کاری نداشته باشید، اون باید شامل همه آیتم ها و path و Border ها بشه. وقتی قراره ItemsPresenter کل فضا رو پوشش بده، معنی نداره که "HorizontalAlignment="Right بشه. هر کاری که می کنید باید در ContentPresenter اون ComboBoxItem باشه که متن آیتم رو نمایش میده.
اشکال کار اینه که شما ستون دوم رو به اندازه طول متن میسازید، نه به اندازه کل فضایی که هست.
شما نوشته اید "ColumnDefinition Width="Auto در حالی که منظورتون "*"=ColumnDefinition Width بوده تا کل فضا رو پوشش بده، نه اینکه به اندازه طول متن ContentPresenter بشه.
وقتی طول ColumnDefinition رو درست مقدار دهی کردید می توانید با اضافه کردن "TextBlock.TextAlignment="Right به اون ContentPresenter متن رو به سمت راست بیارید.

خیلی ممنون استاد . :rose:
هر وقت "Auto" بذاریم ، اندازه ی اون المنت مون ، به اندازه ی محتوای خود همون المنت میشه اما اگه "*" بذاریم ، اندازه ی المنت به اندازه ی کل اون المنت خودش میشه؟

اما در این حالت (که با ItemsPresenter کار نداشته باشم و با ComboBoxItem کار کنم) ، یه مشکل دیگه بوجود میاد .
اینکه من میخوام HorizontalAlignment ئه ContentPresenter (در تمپلیتِ اون ComboBoxItem) را به پروپرتیِ HorizontalContentAlignment ئه کمبوباکس ام بصورت TemplateBinding کنم .
اما نمیدونم چجوری از درون ComboBoxItem ، به پروپرتی های ComboBox ئه مربوط بهش دسترسی داشته باشم (تا TemplateBinding ام را انجام بدم) ؟

BorderThickness رو در Setter قرار ندهید، اجازه بدهید که همیشه BorderThickness ئه 1 باشه. یعنی چه IsHighlighted مقدار true داشته باشه و چه false باشه BorderThickness برابر 1 باشه، گر چه وقتی نمی خواهید دیده بشه BorderBrush اش Transparent باشه.
اینطوری فضای لازم برای اون خط حفظ میشه و دیگه جلوتر نمیره.
فقط BorderBrush رو در Setter تغییر بدهید تا آشکار و مخفی شدن صرفا با تغییر رنگ باشه.
XML:
<Border Name="combItemBorder" Background="Transparent" BorderThickness="1" BorderBrush="Transparent">

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

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

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

XML:
            <ControlTemplate x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="20"/>
                    </Grid.ColumnDefinitions>
                    <Rectangle x:Name="comboboxRectangle" Grid.ColumnSpan="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Height="Auto" RadiusX="3" RadiusY="3" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding BorderBrush}" StrokeThickness="0.5"/>
                    <Path x:Name="Arrow" Grid.Column="1" StrokeThickness="2" StrokeStartLineCap="Triangle" StrokeEndLineCap="Triangle" Stroke="{TemplateBinding BorderBrush}" HorizontalAlignment="Center" VerticalAlignment="Center" Data="M 0 0 L 5 5 L 10 0"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Setter TargetName="comboboxRectangle" Property="Stroke" Value="{DynamicResource comb_Toggle_Border_MouseOverBrush}"/>
                        <Setter TargetName="comboboxRectangle" Property="Fill" Value="{DynamicResource comb_Toggle_Fill_MouseOverBrush}"/>
                        <Setter TargetName="Arrow" Property="Stroke" Value="{DynamicResource comb_Toggle_Border_MouseOverBrush}"/>
                    </Trigger>
                    <Trigger Property="IsChecked" Value="true">
                        <Setter TargetName="comboboxRectangle" Property="Fill" Value="{Binding  Background , RelativeSource={RelativeSource TemplatedParent} }"/>
                        <Setter TargetName="comboboxRectangle" Property="Stroke" Value="{Binding  BorderBrush , RelativeSource={RelativeSource TemplatedParent} }"/>
                        <Setter TargetName="Arrow" Property="Stroke"  Value="{Binding  BorderBrush , RelativeSource={RelativeSource TemplatedParent} }"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter TargetName="comboboxRectangle" Property="Fill" Value="{DynamicResource DisabledBackgroundBrush}"/>
                        <Setter TargetName="comboboxRectangle" Property="Stroke" Value="{DynamicResource DisabledBorderBrush}"/>
                        <Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/>
                        <Setter TargetName="Arrow" Property="Fill" Value="{DynamicResource DisabledForegroundBrush}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>

(بقیه ی کدها ، همون کدهایی هستن که در پست های قبل داده شد) .
نمیشه کاری کرد که با تغییر یک پروپرتی ، کل ToggleButton مون بیاد طرف چپ؟
یعنی جای اون فِلِش (همون Path) که بصورت پیش فرض در سمت راست هست ، به سمت چپ بیاد؟
یا اینکه خودمون باید بصورت دستی با تغییر Trigger و دستکاری هایی در Grid.Column و چیزهای دیگه ، این تغییر را انجام بدیم؟

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

the_king

مدیرکل انجمن
خیلی ممنون استاد . :rose:
هر وقت "Auto" بذاریم ، اندازه ی اون المنت مون ، به اندازه ی محتوای خود همون المنت میشه اما اگه "*" بذاریم ، اندازه ی المنت به اندازه ی کل اون المنت خودش میشه؟
بله.

اما در این حالت (که با ItemsPresenter کار نداشته باشم و با ComboBoxItem کار کنم) ، یه مشکل دیگه بوجود میاد .
اینکه من میخوام HorizontalAlignment ئه ContentPresenter (در تمپلیتِ اون ComboBoxItem) را به پروپرتیِ HorizontalContentAlignment ئه کمبوباکس ام بصورت TemplateBinding کنم .
اما نمیدونم چجوری از درون ComboBoxItem ، به پروپرتی های ComboBox ئه مربوط بهش دسترسی داشته باشم (تا TemplateBinding ام را انجام بدم) ؟
در خود Style ئه SimpleComboBox که هیچ کاری لازم نیست بکنید. ولی در ComboboxItemStyle یک Setter اضافه می کنید تا HorizontalContentAlignment اش رو بر اساس HorizontalContentAlignment کنترل ComboBox (در واقع ItemsControl) تنظیم کنه، HorizontalContentAlignment اش مستقل نباشه :
XML:
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
با اینکار HorizontalContentAlignment رو از SimpleComboBox به ComboBoxItem رسونده اید.
حالا برای ContentPresenter اون HorizontalContentAlignment رو برای HorizontalAlignment استفاده کنید :
XML:
<ContentPresenter x:Name="combItemPresenter" Grid.Column="1" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>

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

XML:
            <ControlTemplate x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="20"/>
                    </Grid.ColumnDefinitions>
                    <Rectangle x:Name="comboboxRectangle" Grid.ColumnSpan="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Height="Auto" RadiusX="3" RadiusY="3" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding BorderBrush}" StrokeThickness="0.5"/>
                    <Path x:Name="Arrow" Grid.Column="1" StrokeThickness="2" StrokeStartLineCap="Triangle" StrokeEndLineCap="Triangle" Stroke="{TemplateBinding BorderBrush}" HorizontalAlignment="Center" VerticalAlignment="Center" Data="M 0 0 L 5 5 L 10 0"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Setter TargetName="comboboxRectangle" Property="Stroke" Value="{DynamicResource comb_Toggle_Border_MouseOverBrush}"/>
                        <Setter TargetName="comboboxRectangle" Property="Fill" Value="{DynamicResource comb_Toggle_Fill_MouseOverBrush}"/>
                        <Setter TargetName="Arrow" Property="Stroke" Value="{DynamicResource comb_Toggle_Border_MouseOverBrush}"/>
                    </Trigger>
                    <Trigger Property="IsChecked" Value="true">
                        <Setter TargetName="comboboxRectangle" Property="Fill" Value="{Binding  Background , RelativeSource={RelativeSource TemplatedParent} }"/>
                        <Setter TargetName="comboboxRectangle" Property="Stroke" Value="{Binding  BorderBrush , RelativeSource={RelativeSource TemplatedParent} }"/>
                        <Setter TargetName="Arrow" Property="Stroke"  Value="{Binding  BorderBrush , RelativeSource={RelativeSource TemplatedParent} }"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter TargetName="comboboxRectangle" Property="Fill" Value="{DynamicResource DisabledBackgroundBrush}"/>
                        <Setter TargetName="comboboxRectangle" Property="Stroke" Value="{DynamicResource DisabledBorderBrush}"/>
                        <Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/>
                        <Setter TargetName="Arrow" Property="Fill" Value="{DynamicResource DisabledForegroundBrush}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>

(بقیه ی کدها ، همون کدهایی هستن که در پست های قبل داده شد) .
نمیشه کاری کرد که با تغییر یک پروپرتی ، کل ToggleButton مون بیاد طرف چپ؟
یعنی جای اون فِلِش (همون Path) که بصورت پیش فرض در سمت راست هست ، به سمت چپ بیاد؟
یا اینکه خودمون باید بصورت دستی با تغییر Trigger و دستکاری هایی در Grid.Column و چیزهای دیگه ، این تغییر را انجام بدیم؟
اگر درست متوجه شده باشم می خواهید در Grid مقدار "FlowDirection="RightToLeft رو اضافه کنید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
در خود Style ئه SimpleComboBox که هیچ کاری لازم نیست بکنید. ولی در ComboboxItemStyle یک Setter اضافه می کنید تا HorizontalContentAlignment اش رو بر اساس HorizontalContentAlignment کنترل ComboBox (در واقع ItemsControl) تنظیم کنه، HorizontalContentAlignment اش مستقل نباشه :

XML:
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>

با اینکار HorizontalContentAlignment رو از SimpleComboBox به ComboBoxItem رسونده اید.

خیلی ممنون استاد .
با توجه به جواب سئوال آخر (قضیه ی FlowDirection که گفتین) ، پس به این جواب از سئوالم هم رسیدم اما چون به درک این جواب نیاز دارم تا سئوالات شبیه این را حل کنم ، این سئوال را میپرسم :

این کد را برای چه Trigger ای (با چه پروپرتی و چه مقداری) در استایلِ ComboboxItemStyle بنویسم؟ (به این معنا نیست که این تریگر را مینویسم چون قضیه FlowDirection را که گفتین اما برای سئوال های مشابه لازم دارم) .
استاد ، من این تیکه ای که نوشتید :

XML:
Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}

را متوجه نشدم .
بی زحمت یه کم بیشتر در این باره توضیح میدین؟
همچنین اون نوعِ ItemsControl را از کجا متوجه شدین بذارین؟

حالا برای ContentPresenter اون HorizontalContentAlignment رو برای HorizontalAlignment استفاده کنید :

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

و به طبع هم متوجه نشدم که در این کد ، اون پروپرتیِ HorizontalContentAlignment ای که TemplateBinding ، از کجا میاد. یا در واقع بذارید این جور بگم که متوجه نشدم پروپرتیِ HorizontalContentAlignment ، چجوری از ComboBox براش ارسال میشه.


اگر درست متوجه شده باشم می خواهید در Grid مقدار "FlowDirection="RightToLeft رو اضافه کنید.

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

the_king

مدیرکل انجمن
خیلی ممنون استاد .
با توجه به جواب سئوال آخر (قضیه ی FlowDirection که گفتین) ، پس به این جواب از سئوالم هم رسیدم اما چون به درک این جواب نیاز دارم تا سئوالات شبیه این را حل کنم ، این سئوال را میپرسم :

این کد را برای چه Trigger ای (با چه پروپرتی و چه مقداری) در استایلِ ComboboxItemStyle بنویسم؟ (به این معنا نیست که این تریگر را مینویسم چون قضیه FlowDirection را که گفتین اما برای سئوال های مشابه لازم دارم).
اون کد برای داخل Trigger قرار دادن نیست، داخل <Style.Setters> قرارش می دهید. Trigger نمی خواد چون شرط خاصی لازم نداره که شرطی اش کنید، در هر حالتی باید ست بشه.

استاد ، من این تیکه ای که نوشتید :

XML:
Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}
را متوجه نشدم .
بی زحمت یه کم بیشتر در این باره توضیح میدین؟
همچنین اون نوعِ ItemsControl را از کجا متوجه شدین بذارین؟
در داخل ComboBoxItem هستیم و میخواهیم HorizontalContentAlignment اون ComboBox رو بدست بیاریم. خود ComboBoxItem هم HorizontalContentAlignment داره چون اونم Control ئه پس باید به طریقی حالی XAML بکنیم که منظورمون HorizontalContentAlignment خود المنت نیست، با اجداد المنت کار داریم. برای اینکه بدونه منظور کدوم HorizontalContentAlignment ئه باید با AncestorType مشخص کنیم که دنبال چه نوع منبعی هستیم. از نوع ComboBox هم می توانید استفاده کنید ولی به هر حال در سلسله وراثت ItemsControl اولویت داره بر ComboBox. اگر بخواهید اولین تفاوت یک شیء ComboBox نسبت به یک شیء ItemsControl رو مشخص کنید اینه که ItemsControl ئه.

این کد HorizontalContentAlignment ای رو Bind می کنه که متعلق به المنت یا والد ای است که ItemsControl باشه. یعنی در سلسله مراتب المنت و والدین اون ComboBoxItem دنبال یک المنت ItemsControl میگرده تا HorizontalContentAlignment اش رو Bind کنه.

بله استاد . همین بود . نام پروپرتی را فراموش کرده بودم .
اما سئوالات مشابه اون سئوال بالا که پرسیدم (یعنی در واقع همون ارتباط برقرار کردنِ بینِ ComboBox و ComboBoxItem را هنوز کامل متوجه نشدم که چجوری هه . مثلا میخوام اگه FlowDirection ئه ComboBox ام تغییری کرد ، به هر نحوی که شده (توسط تریگر یا هر چی) ، ComboBoxItem ام با خبر بشه (و مثلا FlowDirection ئه tickPath ام ، برعکسِ FlowDirection ئه ComboBox ام بشه که حالا این اش مهم نیست . فقط نحوه ی با خبر شدن و اجرای تریگر مهم هه)) .
خیلی ممنون استاد :rose:
طبق همین روال ئه که برای HorizontalContentAlignment داشتید. FlowDirection المنت رو Bind کنید به FlowDirection جد اش.
در مورد RelativeSource و Mode ئه FindAncestor مطالعه کنید. Ancestor یعنی جد، یعنی جد و آباد همون المنتی که داخلش Binding میشه، با AncestorType یا AncestorLevel مشخص می کنند که منظورشون کدوم جد ئه. اگر بخواهید از ComboBox به ComboBoxItem مشخصه ای رو منتقل کنید باید در نظر بگیرید که در سلسله مراتب قرار گیری المنت ها ComboBox جد ComboBoxItem محسوب میشه.
 

SajjadKhati

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

XML:
<Trigger Property="{Binding RelativeSource={RelativeSource AncestorType=ComboBox}, Path=IsFocused}" Value="True">

ارور زیر را میده؟ :

کد:
'A 'Binding' cannot be set on the 'Property' property of type 'Trigger'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.'

پروپرتیِ "Property" (ئه Trigger) ، که هم DependencyProperty و هم خودِ کلاسِ Trigger ، از نوعِ DependencyObject هست و ازش ارث بری میکنه .
پس چرا این ارور را میده؟!

این کد بالا ، داخل کلید ComboBoxToggleButton (که از نوع ToggleButton هست) ، وجود داره که میخوام وقتی پروپرتیِ IsFocused ئه SimpleComboBox (که از نوع ComboBox هست و والدِ ComboBoxToggleButton هم هست) ، مقدار true شد ،
اون تریگر اجرا بشه . که فعلا از پروپرتیِ Tag ئه هر دو شی استفاده کردم .

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

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

ComboBox.PNG

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

نمیشه در xaml کاری کرد که اندازه ی Border ئه همه ی آیتم ها ، به اندازه ی Border ئه بزرگترین آیتم بشه؟
کدی که به این قضیه ربط داره :

XML:
            <Style x:Key="ComboboxItemStyle" TargetType="{x:Type ComboBoxItem}">
                <Style.Setters>
                    <Setter Property="Template">
                        <Setter.Value>

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

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

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

مشکل از کد بخشِ ستونِ <ColumnDefinition Width="*"/> در کد بالاست . که بجای مقدارِ "*" یه جوری باید اندازه ی بزرگترین آیتم ئه کمبوباکس را محاسبه کرد که نمیدونم اصلا در xaml شدنی هست یا فقط توسط کدهای سی شارپ میشه این کار را کرد .

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

کد کامل را در زیر پیوست میکنم (کد پیوست شده ، برای قسمت Resource هست) .
نمونه ی کنترل هم:

XML:
        <ComboBox x:Name="myComboBox" Style="{StaticResource SimpleComboBox}" ItemContainerStyle="{StaticResource ComboboxItemStyle}" Height="28" Margin="10,592,0,0"  VerticalAlignment="Top" Width="201" SelectedIndex="0" HorizontalAlignment="Left" Background="#FF505050" BorderBrush="White" Foreground="White" MaxHeight="150">
            <System:String>salam j j j gj jg k hk j fdgh   fj fj f fj f jff fjfj f jf jf j f  hf f jf jf  fhd  df d dhsd gs d </System:String>
            <System:String>khobi?</System:String>
            <System:String>chetori?</System:String>
            <System:String>kojaee?</System:String>
            <System:String>سلام</System:String>
            <System:String>خوبی؟</System:String>
            <System:String>چطوری؟</System:String>
            <System:String>کجایی!</System:String>
            <System:String>سلام</System:String>
            <System:String>خوبی؟</System:String>
            <System:String>چطوری؟</System:String>
            <System:String>کجایی!</System:String>
            <System:String>سلام</System:String>
            <System:String>خوبی؟</System:String>
            <System:String>چطوری؟</System:String>
            <System:String>کجایی!</System:String>
            <System:String>سلام</System:String>
            <System:String>خوبی؟</System:String>
            <System:String>چطوری؟</System:String>
            <System:String>کجایی!</System:String>
        </ComboBox>

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

بعد اینکه استاد ، پروپرتیِ FrameworkElement.OverridesDefaultStyle چیه که در هر جا تملیت ای که مایکروسافت بکار میبره ، مقدارش را برای همه شون true میکنه . توضیحات سایتش را خوندم ولی خوب متوجه نشدم . واسه اینه که مشخص کنه که این کنترل ، از استایل و تمپلیتِ پیش فرض استفاده میکنه یا نه؟
true یا false کردنش هیچ فرقی نمیکنه انگار .

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

بعد اینکه در استایل ScrollBarThumb ، تریگری برای IsMouseCaptured نوشتم . میخوام هر وقت با موس روی اون دکمه ی Thumb کلیک شد ، اون اتفاقی که نوشتم بیافته . علی الظاهر درست کار میکنه . چون پروپرتیِ IsMouseDown یا IsPressed و اینها را نداشت و دیدم این پروپرتیِ IsMouseCaptured ، کار میکنه ، گذاشتم . واسه ی همین کاره (یعنی وقتی با موس کلیک شه ، مقدارش true میشه) یا واسه ی چیز دیگه ای هست و در شرایط های دیگه ، مشکل پیش میاد؟
توی توضیحاتش نوشته که آیا موس کپچر کرد این المنت را یا نه .

ممنون استاد .
 

پیوست ها

  • ComboBox Template.txt
    22.3 کیلوبایت · بازدیدها: 0

the_king

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

XML:
<Trigger Property="{Binding RelativeSource={RelativeSource AncestorType=ComboBox}, Path=IsFocused}" Value="True">

ارور زیر را میده؟ :

کد:
'A 'Binding' cannot be set on the 'Property' property of type 'Trigger'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.'
چون چیزی که نوشته اید بی معنیه. Trigger میگه که اگر فلان مشخصه مقدار بهمان رو داشت بیا و فلان کار ها رو انجام بده.
اما شما نوشته اید بیا IsFocused ئه ComboBox ای که در جد و آباد این المنت پیدا می کنی رو Bind کن به خدا میدونه چی، به چی Bind کنه؟ و بعد چک کنه که مقدار اش True هست یا اینکه بیاد مقدارش رو True کنه؟ بالاخره این Trigger ئه یا Setter با Binding ئه؟ Trigger از شما شرط می خواهد، چرا داخلش Binding داره؟ اون Value که نمیتونه هم شرط باشه و هم مقدار اش رو Set کنه.

پروپرتیِ "Property" (ئه Trigger) ، که هم DependencyProperty و هم خودِ کلاسِ Trigger ، از نوعِ DependencyObject هست و ازش ارث بری میکنه .
پس چرا این ارور را میده؟!
آخه این Trigger ای که نوشته اید از دید شما قراره چه معنی ای داشته باشه؟ یعنی چی که مشخصه ای از نوع boolean بیاد Binding بشه به Property که
اسم یک مشخصه رو ازتون میخواد.

این کد بالا ، داخل کلید ComboBoxToggleButton (که از نوع ToggleButton هست) ، وجود داره که میخوام وقتی پروپرتیِ IsFocused ئه SimpleComboBox (که از نوع ComboBox هست و والدِ ComboBoxToggleButton هم هست) ، مقدار true شد ،
اون تریگر اجرا بشه . که فعلا از پروپرتیِ Tag ئه هر دو شی استفاده کردم .
XML:
                <DataTrigger Binding="{Binding Path=IsFocused, RelativeSource={RelativeSource AncestorType=ComboBox}}" Value="True">
                    <Setter ... />
                </DataTrigger>

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

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

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


نمیشه در xaml کاری کرد که اندازه ی Border ئه همه ی آیتم ها ، به اندازه ی Border ئه بزرگترین آیتم بشه؟
حتما راه حلی داره اما بعید میدونم که فقط با XAML عملی باشه.


بعد اینکه استاد ، پروپرتیِ FrameworkElement.OverridesDefaultStyle چیه که در هر جا تملیت ای که مایکروسافت بکار میبره ، مقدارش را برای همه شون true میکنه . توضیحات سایتش را خوندم ولی خوب متوجه نشدم . واسه اینه که مشخص کنه که این کنترل ، از استایل و تمپلیتِ پیش فرض استفاده میکنه یا نه؟
true یا false کردنش هیچ فرقی نمیکنه انگار .
مشخص می کنه که آیا مواردی که در Style تون صریحا مشخص نکرده اید از Style پیشفرض تاثیر بگیرند یا نه.
چرا، خیلی تاثیر داره، مثلا این Style زمینه رو قرمز می کنه اما شیوه نمایش متن و کادر و افکت های دیگه دکمه پیشفرض رو همچنان داره :
XML:
            <Style TargetType="Button">
                <Setter Property="OverridesDefaultStyle" Value="False" />
                <Setter Property="Background" Value="Red"/>
            </Style>
اما این Style کلا تاثیر Style پیشفرض رو از بین میبره و چون خودش هم فقط زمینه رو قرمز می کنه و اون مشخصه Background رو هم در رسم هیچ المنت ای بکار نمیره و توصیف ظاهری برای دکمه نداره، اصلا چیزی از دکمه دیده نمیشه :
XML:
            <Style TargetType="Button">
                <Setter Property="OverridesDefaultStyle" Value="True" />
                <Setter Property="Background" Value="Red"/>
            </Style>

بعد اینکه در استایل ScrollBarThumb ، تریگری برای IsMouseCaptured نوشتم . میخوام هر وقت با موس روی اون دکمه ی Thumb کلیک شد ، اون اتفاقی که نوشتم بیافته . علی الظاهر درست کار میکنه . چون پروپرتیِ IsMouseDown یا IsPressed و اینها را نداشت و دیدم این پروپرتیِ IsMouseCaptured ، کار میکنه ، گذاشتم . واسه ی همین کاره (یعنی وقتی با موس کلیک شه ، مقدارش true میشه) یا واسه ی چیز دیگه ای هست و در شرایط های دیگه ، مشکل پیش میاد؟
توی توضیحاتش نوشته که آیا موس کپچر کرد این المنت را یا نه .
برای وقتی است که بخاطر عملیات Drag باید اطلاعات ماوس به اون المنت ارسال بشه، حتی اگه ماوس روی اون المنت قرار نداشته باشه. اگر کار می کنه می توانید ازش استفاده کنید، اما کاری که انجام می دهید غیر عادی است.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
چون چیزی که نوشته اید بی معنیه. Trigger میگه که اگر فلان مشخصه مقدار بهمان رو داشت بیا و فلان کار ها رو انجام بده.
اما شما نوشته اید بیا IsFocused ئه ComboBox ای که در جد و آباد این المنت پیدا می کنی رو Bind کن به خدا میدونه چی، به چی Bind کنه؟ و بعد چک کنه که مقدار اش True هست یا اینکه بیاد مقدارش رو True کنه؟ بالاخره این Trigger ئه یا Setter با Binding ئه؟ Trigger از شما شرط می خواهد، چرا داخلش Binding داره؟ اون Value که نمیتونه هم شرط باشه و هم مقدار اش رو Set کنه.


آخه این Trigger ای که نوشته اید از دید شما قراره چه معنی ای داشته باشه؟ یعنی چی که مشخصه ای از نوع boolean بیاد Binding بشه به Property که
اسم یک مشخصه رو ازتون میخواد.


XML:
                <DataTrigger Binding="{Binding Path=IsFocused, RelativeSource={RelativeSource AncestorType=ComboBox}}" Value="True">
                    <Setter ... />
                </DataTrigger>

سلامی مجدد
خیلی ممنون استاد :rose:
این قضیه ی DataTrigger کجا بود . چقدر کاربردی هه .
خیلی ممنون .
پس DataTrigger زمانی به درد میخوره که بخوایم مقدار پروپرتی ای را توسط بایند کردن ، بدست بیاریم که فلان مقدار هست یا نه (توسط پروپرتیِ Binding ئه DataTrigger . عملیاتِ بایند کردن را روی همین پروپرتیِ Binding ئه DataTrigger انجام میدیم) . درسته؟

استاد ، همین قضیه ، برای رویدادها نمیشه؟ البته منظورم ، بایند کردن نیست . منظورم اینه که مثلا یه رویدادی را یه کنترلِ پدر داره که کنترلِ فرزندش نداره و به شیوه ای شبیه این ، همین کار را کنیم تا بتونیم از رویدادی که در کنترل پدر اتفاق میافته ، در تگ فرزند هم با خبر بشیم (مثلا رویدادی که در combobox اتفاق میافته را در تگ comboboxitem متوجه بشیم) .

حتما راه حلی داره اما بعید میدونم که فقط با XAML عملی باشه.

آره .
من هم بعید میدونم توی xaml شدنی باشه . چون نیاز به گرفتن مقادیرِ همه ی آیتم ها و مقایسه کردن بین همه ی آیتم ها را داره .

مشخص می کنه که آیا مواردی که در Style تون صریحا مشخص نکرده اید از Style پیشفرض تاثیر بگیرند یا نه.
چرا، خیلی تاثیر داره، مثلا این Style زمینه رو قرمز می کنه اما شیوه نمایش متن و کادر و افکت های دیگه دکمه پیشفرض رو همچنان داره :
XML:
            <Style TargetType="Button">
                <Setter Property="OverridesDefaultStyle" Value="False" />
                <Setter Property="Background" Value="Red"/>
            </Style>
اما این Style کلا تاثیر Style پیشفرض رو از بین میبره و چون خودش هم فقط زمینه رو قرمز می کنه و اون مشخصه Background رو هم در رسم هیچ المنت ای بکار نمیره و توصیف ظاهری برای دکمه نداره، اصلا چیزی از دکمه دیده نمیشه :
XML:
            <Style TargetType="Button">
                <Setter Property="OverridesDefaultStyle" Value="True" />
                <Setter Property="Background" Value="Red"/>
            </Style>

اما پس زمانی که تمپلیت درست میکنیم ، فرقی نداره .
زمان ایجاد تمپلیت ، توی هر دوش ، پروپرتیِ Background نادیده گرفته میشه .

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

خیلی ممنون .

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

استاد ، توی تمپلیت ای که برای کمبوباکس ساخته شد ، اگه بخوام زمانی که اون popup (با نام PART_Popup) ئه کمبوباکس بسته میشه ، انیمیشن ای اجرا کنم ، باید توی چه رویدادی از popup این کار را انجام بدم؟
گشتم ، ولی رویدادی که قبل از اینکه popup بسته بشه ، اجرا بشه (یعنی مثلا Closing باشه) ، نبود . فقط رویداد Closed بود که بعد از بسته شدن popup اجرا میشه که چون بسته شد و تموم شد ، دیگه انیمیشن کردنش فایده ای نداره .
رویدادی برای این کار هست؟ اگه آره ، چه رویدادی؟

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

the_king

مدیرکل انجمن
سلامی مجدد
خیلی ممنون استاد :rose:
این قضیه ی DataTrigger کجا بود . چقدر کاربردی هه .
خیلی ممنون .
پس DataTrigger زمانی به درد میخوره که بخوایم مقدار پروپرتی ای را توسط بایند کردن ، بدست بیاریم که فلان مقدار هست یا نه (توسط پروپرتیِ Binding ئه DataTrigger . عملیاتِ بایند کردن را روی همین پروپرتیِ Binding ئه DataTrigger انجام میدیم) . درسته؟
همه Trigger ها کاربردی هستند و در موارد متفاوتی بدرد میخورند، با یکی دو مثال نمیشه کاربرد ها رو محدود کرد.

استاد ، همین قضیه ، برای رویدادها نمیشه؟ البته منظورم ، بایند کردن نیست . منظورم اینه که مثلا یه رویدادی را یه کنترلِ پدر داره که کنترلِ فرزندش نداره و به شیوه ای شبیه این ، همین کار را کنیم تا بتونیم از رویدادی که در کنترل پدر اتفاق میافته ، در تگ فرزند هم با خبر بشیم (مثلا رویدادی که در combobox اتفاق میافته را در تگ comboboxitem متوجه بشیم) .
اگر خیلی اهمیت داشته باشه که هدایت رخداد رو در وراثت کلاس انجام می دهید، یا اصلا یک EventTrigger اختصاصی برای این منظور طراحی می کنید.
اما در حالت ساده اش با یک متد در والد رخداد رو می توانید دریافت کنید و بر اساسش کاری رو انجام بدهید.
اینکه در یک برنامه به زبان #C کاری رو بدون کدنویسی #C انجام بدهید مزیت خاصی نیست، لازم نیست که حتما همه کار رو با XAML خالی انجام بدهید.


اما پس زمانی که تمپلیت درست میکنیم ، فرقی نداره .
زمان ایجاد تمپلیت ، توی هر دوش ، پروپرتیِ Background نادیده گرفته میشه .
نمیدونم چطور همچین نتیجه ای گرفتید ولی به هر حال نتیجه گیری تون اشتباه ئه.
چه Template درست بکنید و چه نکنید، مقدار مشخصه OverridesDefaultStyle روی تاثیر گذاشتن و نذاشتن Style پیشفرض تعیین کننده است.
شما میگید که این :
XML:
            <Style TargetType="Button">
                <Setter Property="OverridesDefaultStyle" Value="True" />
                <Setter Property="Background" Value="Red"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="Button">
                            <Grid Background="{TemplateBinding Background}">
                                <Grid Background="Yellow" Width="20" Height="20" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
با این فرقی نداره :
XML:
            <Style TargetType="Button">
                <Setter Property="OverridesDefaultStyle" Value="False" />
                <Setter Property="Background" Value="Red"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="Button">
                            <Grid Background="{TemplateBinding Background}">
                                <Grid Background="Yellow" Width="20" Height="20" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
در حالی که به وضوح ظاهر متفاوتی دارند. اگر در ControlTemplate تون مقدار HorizontalContentAlignment رو مشخص نکنید با توجه به وضعیت OverridesDefaultStyle مقداری که {TemplateBinding HorizontalContentAlignment} میده متفاوت ئه، Left با Center فرق داره.

استاد ، توی تمپلیت ای که برای کمبوباکس ساخته شد ، اگه بخوام زمانی که اون popup (با نام PART_Popup) ئه کمبوباکس بسته میشه ، انیمیشن ای اجرا کنم ، باید توی چه رویدادی از popup این کار را انجام بدم؟
گشتم ، ولی رویدادی که قبل از اینکه popup بسته بشه ، اجرا بشه (یعنی مثلا Closing باشه) ، نبود . فقط رویداد Closed بود که بعد از بسته شدن popup اجرا میشه که چون بسته شد و تموم شد ، دیگه انیمیشن کردنش فایده ای نداره .
رویدادی برای این کار هست؟ اگه آره ، چه رویدادی؟
PopupAnimation براتون مزاحمت ایجاد می کنه چون قراره انیمیشن رو اون انجام بده. اما در کل بجای اینکه IsOpen رو TemplateBinding کنید، می توانید خودتون بر اساس IsDropDownOpen تغییر مقدار IsOpen رو به عهده بگیرید و در خلال انجام اینکار کار دیگری هم انجام بدهید.
 

SajjadKhati

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

خیلی ممنون استاد (هم درباره ی جواب قسمت های دیگه . البته درباره ی اون کدتون ، ان شاء الله بعدا صحبت میکنیم . تشکر) .
استاد ، از پروپرتیِ IsDropDownOpen به عنوان شرطی برای تریگر نمیتونم استفاده کنم . چون تریگری که نهایتا بتونیم بهش StoryBoard بدیم ، پروپرتیِ Actions ئه EventTrigger هست (که از نوع TriggerActionCollection) هست .
کلاس Trigger ، پروپرتی از از نوع TriggerAction نداره تا بهش برای انیمیشن ، مقدار StoryBoard بدیم .

توی EventTrigger هم که پروپرتیِ RoutedEvent ، فقط رویدادهای routed event را قبول میکنه . رویداد ComboBox.DropDownOpened هم که routed event نیست و قبول نمیکنه .
رویداد جایگزینی برای این کار هست؟ یا راهکار دیگه ای برای انیمیشن کردن؟
تشکر استاد .
 

the_king

مدیرکل انجمن
خیلی ممنون استاد (هم درباره ی جواب قسمت های دیگه . البته درباره ی اون کدتون ، ان شاء الله بعدا صحبت میکنیم . تشکر) .
استاد ، از پروپرتیِ IsDropDownOpen به عنوان شرطی برای تریگر نمیتونم استفاده کنم . چون تریگری که نهایتا بتونیم بهش StoryBoard بدیم ، پروپرتیِ Actions ئه EventTrigger هست (که از نوع TriggerActionCollection) هست .
عجب. جالبه. در Trigger.EnterActions و Trigger.ExitActions هم که لابد Storyboard نمیشه اضافه کرد.

کلاس Trigger ، پروپرتی از از نوع TriggerAction نداره تا بهش برای انیمیشن ، مقدار StoryBoard بدیم .
بله ولی EnterActions و ExitActions که داره.

توی EventTrigger هم که پروپرتیِ RoutedEvent ، فقط رویدادهای routed event را قبول میکنه . رویداد ComboBox.DropDownOpened هم که routed event نیست و قبول نمیکنه .
رویداد جایگزینی برای این کار هست؟ یا راهکار دیگه ای برای انیمیشن کردن؟
تشکر استاد .
از این لحاظ مشکلی وجود نداره، اگر جستجو کنید روش های متفاوتی مثل تعریف کردن TriggerAction اختصاصی هم هست، اما همانطور که گفتم انیمیشن Popup با انیمیشن شما تداخل خواهند داشت.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
عجب. جالبه. در Trigger.EnterActions و Trigger.ExitActions هم که لابد Storyboard نمیشه اضافه کرد.


بله ولی EnterActions و ExitActions که داره.


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

آها خیلی ممنون استاد .
چون زمانی که قبلا با EventTrigger آشنا شده بودم ، هشدار داده بود که بهتره بجای پروپرتیِ EnterActions و ExitActions ، از پروپرتیِ Actions استفاده کنید (دقیق نمیدونم چرا) .
استاد ، الان در کد زیر ، نمیدونم چرا رویداد StoryboardPopupOpen_Completed ، اجرا نمیشه :


XML:
            <!-- SimpleComboBox -->
            <Style x:Key="SimpleComboBox" TargetType="{x:Type ComboBox}">
                <Setter Property="SnapsToDevicePixels" Value="False"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ComboBox}">
                            <Grid>
                                <!--Template="{DynamicResource ComboBoxTextBox}"-->

                                <!--The ToggleButton is databound to the ComboBox itself to toggle IsDropDownOpen-->
                                <ToggleButton x:Name="ToggleButton" Template="{DynamicResource ComboBoxToggleButton}" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" Foreground="{TemplateBinding Foreground}" Focusable="False" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press"/>
                                <ContentPresenter  x:Name="ContentSite" VerticalAlignment="Center"  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="6,-2,20,0" IsHitTestVisible="False" TextBlock.Foreground="{TemplateBinding Foreground}" Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"/>

                                <!--The TextBox must be named PART_EditableTextBox or ComboBox will not recognize it-->
                                <TextBox x:Name="PART_EditableTextBox" Template="{DynamicResource TextBoxOfComboBoxTemplate}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,20,0" Focusable="True" Background= "{DynamicResource TextBoxOfComboBoxBackground}" Foreground="{TemplateBinding Foreground}" Visibility="Hidden" IsReadOnly="{TemplateBinding IsReadOnly}" BorderBrush="{TemplateBinding BorderBrush}"/>
                                <!--The Popup shows the list of items in the ComboBox. IsOpen is databound to IsDropDownOpen which is toggled via the ComboBoxToggleButton-->
                                <Popup x:Name="PART_Popup" Height="3" Placement="Bottom" Focusable="False" AllowsTransparency="True"  MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{TemplateBinding ActualWidth}" MaxWidth="{TemplateBinding ActualWidth}">
                                    <Grid x:Name="DropDown" SnapsToDevicePixels="True">
                                        <Border x:Name="DropDownBorder" Background="{DynamicResource comb_Pop_Fill_Brush}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1"/>
                                        <ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" CanContentScroll="True">

                                            <ItemsPresenter/>

                                        </ScrollViewer>
                                    </Grid>
                                </Popup>
                            </Grid>
                            
                            <ControlTemplate.Triggers>
                                <!--This forces the DropDown to have a minimum size if it is empty-->
                                <Trigger Property="HasItems" Value="false">
                                    <Setter Property="MinHeight" Value="40" TargetName="DropDownBorder"/>
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="false">
                                    <Setter TargetName="PART_EditableTextBox" Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/>
                                    <Setter TargetName="PART_EditableTextBox" Property="Background" Value="{DynamicResource  DisabledBackgroundBrush}"/>
                                    <Setter  TargetName="PART_EditableTextBox" Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" />
                                </Trigger>
                                <Trigger Property="IsGrouping" Value="true">
                                    <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                                </Trigger>
                                <Trigger Property="AllowsTransparency" SourceName="PART_Popup" Value="true">
                                    <Setter Property="CornerRadius" Value="4" TargetName="DropDownBorder"/>
                                </Trigger>
                                <Trigger Property="IsEditable" Value="true">
                                    <Setter Property="IsTabStop" Value="false"/>
                                    <Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible"/>
                                    <Setter TargetName="ContentSite" Property="Visibility" Value="Hidden"/>
                                </Trigger>
                                <Trigger Property="IsDropDownOpen" Value="True">
                                    <Setter TargetName="PART_Popup" Property="IsOpen" Value="True"/>
                                    <Trigger.EnterActions>
                                        <BeginStoryboard>
                                            <Storyboard Name="StoryboardPopupOpen" Storyboard.TargetName="PART_Popup" Storyboard.TargetProperty="Height" FillBehavior="Stop" Completed="StoryboardPopupOpen_Completed">
                                                <DoubleAnimationUsingKeyFrames Duration="0:0:0.5">
                                                    <SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="150" KeySpline="0.25,0.25  0.75,0.75"/>
                                                </DoubleAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </Trigger.EnterActions>
                                </Trigger>
                                <Trigger Property="IsDropDownOpen" Value="False">
                                    <Setter TargetName="PART_Popup" Property="IsOpen" Value="False"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

و در سی شارپ :

C#:
        private void StoryboardPopupOpen_Completed(object sender, EventArgs e)
        {
            Popup popup =(Popup)Storyboard.GetTarget(sender as DependencyObject);
            popup.Height = 360;
            //MessageBox.Show("hjkh");
        }

بریک پوینت میذارم . MessageBox.Show میذارم . هیچ کدوم را اجرا نمیکنه . نمیدونم چرا .
میخوام وقتی انیمیشن تمام شد ، مقدار Height ئه اون Popup را که 3 هست را تغییر بده (به اندازه ی MaxHeight ئه Popup کنه) .
مشکل از کجاست که اصلا اون رویداد اجرا نمیشه؟


و اینکه استاد ، wpf ، کنترلِ numericupdown نداره . به نظرتون من که میخوام کمترین میزان استفاده را از کتابخونه های خارجی (برای استفاده از کنترل ها) کنم (اگه بخوام استفاده کنم ، حجم کل کتابخونه های استفاده شده ی خارجی برای کل کنترل هام میخوام حداکثر زیر 1 مگابایت باشه) ، بهتره که این کنترل را از nuget دانلود کنم (چند تا کنترل numericupdown که سازنده های مختلفی دارن ، در nuget هست) یا اینکه از کمپوننت و کنترل هایی که شرکت های مختلف تولید کردن ، استفاده کنم یا اینکه خودم بسازم؟

تشکر استاد .
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
نمیدونم چطور همچین نتیجه ای گرفتید ولی به هر حال نتیجه گیری تون اشتباه ئه.
چه Template درست بکنید و چه نکنید، مقدار مشخصه OverridesDefaultStyle روی تاثیر گذاشتن و نذاشتن Style پیشفرض تعیین کننده است.
شما میگید که این :
XML:
            <Style TargetType="Button">
                <Setter Property="OverridesDefaultStyle" Value="True" />
                <Setter Property="Background" Value="Red"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="Button">
                            <Grid Background="{TemplateBinding Background}">
                                <Grid Background="Yellow" Width="20" Height="20" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
با این فرقی نداره :
XML:
            <Style TargetType="Button">
                <Setter Property="OverridesDefaultStyle" Value="False" />
                <Setter Property="Background" Value="Red"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="Button">
                            <Grid Background="{TemplateBinding Background}">
                                <Grid Background="Yellow" Width="20" Height="20" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
در حالی که به وضوح ظاهر متفاوتی دارند. اگر در ControlTemplate تون مقدار HorizontalContentAlignment رو مشخص نکنید با توجه به وضعیت OverridesDefaultStyle مقداری که {TemplateBinding HorizontalContentAlignment} میده متفاوت ئه، Left با Center فرق داره.


خیلی ممنون استاد .
چی شد استاد؟
چرا HorizontalContentAlignment ئه دکمه در کد اول را با اونکه مشخص نکردیم (و مقدارش هم همون مقدار پیش فرض هست . و مقدار پیش فرض اش هم Center هست) ، پس چرا HorizontalAlignment ئه اون Grid ئه داخلی که بهش بایند شده ، به سمت چپ (Left) رفت؟!!

باز جای تعجب بیشتر اینجاست که واسه ی من ، موقعی که در زمان طراحی هست ، هر دو دکمه ، شکلی دقیق مثل هم دارن اما فقط زمان اجرا ، اون Grid ئه داخلی (که زرد هست) ، به HorizontalAlignment اش Left میشه و به سمت چپِ Button میره .
چرا این طوره؟ و هم اینکه چرا زمان اجرا با زمانی که برنامه اجرا نیست ، فرق داره؟

پس وقتی پروپرتیِ OverridesDefaultStyle ، مقدارش False باشه ، بهتره که . چون در این طراحی (در این دو کد) ، حداقل من انتظاارِ شکل کدِ دوم را با این کد دارم .
 

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

بالا