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

the_king

مدیرکل انجمن
استاد ، الان در کد زیر ، نمیدونم چرا رویداد 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 کنه) .
مشکل از کجاست که اصلا اون رویداد اجرا نمیشه؟
sender ئه Clock ئه. توضیحات بخش Remark رو برای رخداد Timeline.Completed در سایت مایکروسافت بخونید.
XML:
    <Window.Resources>
        <Storyboard Completed="StoryboardPopupOpen_Completed" FillBehavior="Stop" x:Key="StoryboardPopupOpen" Storyboard.TargetName="PART_Popup" Storyboard.TargetProperty="Height" Duration="0:0:0.5">
            <DoubleAnimationUsingKeyFrames>
                <SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="150" KeySpline="0.25,0.25  0.75,0.75"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </Window.Resources>
XML:
                                <Trigger Property="IsDropDownOpen" Value="True">
                                    <Setter TargetName="PART_Popup" Property="IsOpen" Value="True"/>
                                    <Trigger.EnterActions>
                                        <BeginStoryboard Storyboard="{StaticResource StoryboardPopupOpen}"/>
                                    </Trigger.EnterActions>
                                </Trigger>
و اینکه استاد ، wpf ، کنترلِ numericupdown نداره . به نظرتون من که میخوام کمترین میزان استفاده را از کتابخونه های خارجی (برای استفاده از کنترل ها) کنم (اگه بخوام استفاده کنم ، حجم کل کتابخونه های استفاده شده ی خارجی برای کل کنترل هام میخوام حداکثر زیر 1 مگابایت باشه) ، بهتره که این کنترل را از nuget دانلود کنم (چند تا کنترل numericupdown که سازنده های مختلفی دارن ، در nuget هست) یا اینکه از کمپوننت و کنترل هایی که شرکت های مختلف تولید کردن ، استفاده کنم یا اینکه خودم بسازم؟
باید بر اساس شرایط خودتون تصمیم بگیرید، نظر من بر اساس توانایی و قابلیت های خودم خواهد بود و بدرد شخص دیگری نمیخوره.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
sender ئه Clock ئه. توضیحات بخش Remark رو برای رخداد Timeline.Completed در سایت مایکروسافت بخونید.
XML:
    <Window.Resources>
        <Storyboard Completed="StoryboardPopupOpen_Completed" FillBehavior="Stop" x:Key="StoryboardPopupOpen" Storyboard.TargetName="PART_Popup" Storyboard.TargetProperty="Height" Duration="0:0:0.5">
            <DoubleAnimationUsingKeyFrames>
                <SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="150" KeySpline="0.25,0.25  0.75,0.75"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </Window.Resources>
XML:
                                <Trigger Property="IsDropDownOpen" Value="True">
                                    <Setter TargetName="PART_Popup" Property="IsOpen" Value="True"/>
                                    <Trigger.EnterActions>
                                        <BeginStoryboard Storyboard="{StaticResource StoryboardPopupOpen}"/>
                                    </Trigger.EnterActions>
                                </Trigger>
سلامی مجدد
خیلی ممنون استاد . :rose:

آو!! چی شده؟
انگار نباید بین کد من و شما فرقی داشته باشه . فرقش چیه که در کد شما اون رویداد اجرا میشه ولی در کد من نمیشه؟!!
صرفا بخاطر اینکه کدتون را در resource گذاشتین که نیست؟ هست؟ کلا ممنون میشم بیشتر دلیلش را توضیح بدید .

هم اینکه وقتی با SplineDoubleKeyFrame ، انیمیشن میکنم ، مثل بازی که میکنن ، وقتی فریم کم بده ، باعث پَرِش در تصویر میشه . این هم همینطوره . اما وقتی با LinearDoubleKeyFrame انیمیشن کنم ، خوب و انیمیشن ، روان هست . چرا؟

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

استاد ، بی زحمت جواب پست قبلی (380) را هم میدین؟
تشکر
 

the_king

مدیرکل انجمن
چی شد استاد؟
چرا HorizontalContentAlignment ئه دکمه در کد اول را با اونکه مشخص نکردیم (و مقدارش هم همون مقدار پیش فرض هست . و مقدار پیش فرض اش هم Center هست) ، پس چرا HorizontalAlignment ئه اون Grid ئه داخلی که بهش بایند شده ، به سمت چپ (Left) رفت؟!!
تفاوت دو تا کد رو که می بینید. مقدار پیشفرض مشخصه اش که Center نیست، مقدار پیشفرض مشخصه اش Left ئه، اون پیشفرض Center مربوط به Style پیشفرض ئه که با Setter تنظیمش کرده و با OverridesDefaultStyle گفتیم که Style پیشفرض رو بذاره کنار و تاثیری نداشته باشه. در نتیجه Left ئه Left میمونه و Style پیشفرضی هم اعمال نشده که Center اش کنه.

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

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


آو!! چی شده؟
انگار نباید بین کد من و شما فرقی داشته باشه . فرقش چیه که در کد شما اون رویداد اجرا میشه ولی در کد من نمیشه؟!!
صرفا بخاطر اینکه کدتون را در resource گذاشتین که نیست؟ هست؟ کلا ممنون میشم بیشتر دلیلش را توضیح بدید .
مستندات خاصی نداره که بتوانم به اون استناد کنم. در ظاهر اتصال به رخداد باید قبل از اینکه انیمیشن شروع به اجرا کنه انجام شده باشه و وقتی در BeginStoryboard المنت Storyboard رو توصیف می کنید توصیف Storyboard و اتصال به رخداد و اجرای Storyboard ترتیب مناسبی رو طی نمی کنه.
با قرار دادنش داخل Resources دیگه قبل از اینکه انیمیشن بخواد اجرا بشه توصیف Storyboard و اتصال رخداد صورت گرفته و مشکل حل میشه.

هم اینکه وقتی با SplineDoubleKeyFrame ، انیمیشن میکنم ، مثل بازی که میکنن ، وقتی فریم کم بده ، باعث پَرِش در تصویر میشه . این هم همینطوره . اما وقتی با LinearDoubleKeyFrame انیمیشن کنم ، خوب و انیمیشن ، روان هست . چرا؟
چون انیمیشن در نخ مستقلی مدیریت میشه و برای همین بصورت پیشفرض زمان بندی خیلی دقیقی نداره. جایی این ناهماهنگی خودش رو نشون میده که تغییرات سریعی رخ بده و نیاز به نمایش سریع تغییرات باشه. LinearDoubleKeyFrame بخاطر ماهیت خطی اش تغییرات یکنواخت ئه و دقیق بودن زمان بندی رویش تاثیر محسوسی نمیذاره ولی در SplineDoubleKeyFrame منحنی شما ممکنه یکجا شیب تند و یکجا شیب ملایم داشته باشه و تغییرات یکنواخت نیست، در جاهایی که شیب تند ئه از دست دادن زمان بندی تاثیر محسوسی میذاره.

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

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
تفاوت دو تا کد رو که می بینید. مقدار پیشفرض مشخصه اش که Center نیست، مقدار پیشفرض مشخصه اش Left ئه، اون پیشفرض Center مربوط به Style پیشفرض ئه که با Setter تنظیمش کرده و با OverridesDefaultStyle گفتیم که Style پیشفرض رو بذاره کنار و تاثیری نداشته باشه. در نتیجه Left ئه Left میمونه و Style پیشفرضی هم اعمال نشده که Center اش کنه.


قاعدتا کدی که نوشته اید یک ایرادی داره وگرنه من همچین ظاهری که شما توصیف می کنید نمی بینم. بعید هم میدونم ایراد ویژوال استدیو تون باشه.

از شما هر کدوم میتونه بهتر یا بدتر باشه ولی اینکه شما چه انتظاری داشته باشید ملاک شخصی شما است، ملاک فنی نیست.
خیلی ممنون استاد :rose:
من دقیق متوجه نشدم .
هر button ای را که گذاشتم ، مقدار پیش فرض HorizontalContentAlignment اش Center بود . left نبود .

مستندات خاصی نداره که بتوانم به اون استناد کنم. در ظاهر اتصال به رخداد باید قبل از اینکه انیمیشن شروع به اجرا کنه انجام شده باشه و وقتی در BeginStoryboard المنت Storyboard رو توصیف می کنید توصیف Storyboard و اتصال به رخداد و اجرای Storyboard ترتیب مناسبی رو طی نمی کنه.
با قرار دادنش داخل Resources دیگه قبل از اینکه انیمیشن بخواد اجرا بشه توصیف Storyboard و اتصال رخداد صورت گرفته و مشکل حل میشه.
آها .
ولی نمیدونم چرا یه انیمیشن دیگه را که قبلا همینطوری درست کرده بودم و توی resource نذاشته بودم ، برای اجرای رویداد Completed اش مشکلی نداشت و اجرا شد . منتها بجای Trigger ، توی EventTrigger نوشته بودم (پروپرتیِ Actions اش) . حالا نمیدونم به این ربط داره یا نه .

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

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

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

استاد ، من الان میخوام توی رویداد StoryboardPopupOpen_Completed ، مقدار Height ئه اون PART_Popup را تغییر بدم .
به نظرتون چه راهکاری ، ساده ترین کار برای این قضیه هست؟

1) اینکه اون Popup (که نامش PART_Popup هست) را بصورت جداگانه در Resource تعریف کنم و در اون SimpleComboBox ، بصورت DynamicResource ازش استفاده کنم (یا حتی بجای کلِ Popup ، فقط نوعِ Double ای که مشخص کننده ی مقدار Height هست را در Resource ذخیره کنم) و موقع اجرای این رویدادِ StoryboardPopupOpen_Completed ، مقدارِ Double در اون Resource (یا پروپرتیِ Height ئه PART_Popup در Resource) را تغییر بدم.

2) یا اینکه در خودِ رویداد StoryboardPopupOpen_Completed ، از sender ، مقدار Storyboard ای که مربوط بهش میشه را بگیرم و این شیِ PART_Popup را توسط متد Storyboard.GetTarget برگردونم؟
اگه به این روش برم ، کد زیر را در رویداد StoryboardPopupOpen_Completed نوشتم :

C#:
            ClockGroup clockGroup  = sender as ClockGroup;
            TimelineGroup timelineGroup = clockGroup.Timeline;

            Object obj = Storyboard.GetTarget(timelineGroup);
دو خط اول مشکلی ندارن اما خط آخر ، مقدار obj را null برمیگردونه .
نمیدونم چجوری sender را به شیِ Storyboard اش تبدیل کنم .

3) یا اینکه روش دیگه ای هم هست؟
 

the_king

مدیرکل انجمن
خیلی ممنون استاد :rose:
من دقیق متوجه نشدم .
هر button ای را که گذاشتم ، مقدار پیش فرض HorizontalContentAlignment اش Center بود . left نبود .
من نمیدونم شما چه کدی نوشته اید.

البته توی SplineDoubleKeyFrame هم فعلا اون KeySpline را جوری تنظیم کردم که بصورت خطی باشه . باز هم ریپ میزنه . پس واسه ی سخت افزار کامپیوتر من نیست و مشکل از طراحی این کلاس هه؟
قطعا با سخت افزار قوی تر بهتر میشه اما در کل مربوط به معماری WPF ئه و مشکل صرفا شما نیست :

منظورم از کنترل های مهم ، کنترل های پر کاربرد (حداقل برای من) هستند . مثل کمبوباکس و tabcontrol و لیست باکس و اینها که خودم تمپلیت براشون میسازم ولی اینکه بخوام تا کوچیک ترین کنترل هایی که استفاده میکنم را براشون تمپلیت بسازم ، خیلی طول میکشه و فکر میکنم بجای اون کنترل هایی که نسبت به اینها برام کاربرد کمتری دارن ، کمپوننت ای را استفاده کنم ، بهتر باشه .
کلا شما اصلا از کمپوننت و اینها استفاده نمیکنین؟
کنترل نه، ولی کمپوننت چرا، از Aspose.Cells و Aspose.Words و Saraff.Twain و ZXing.Net و Magick.NET و ...

استاد ، من الان میخوام توی رویداد StoryboardPopupOpen_Completed ، مقدار Height ئه اون PART_Popup را تغییر بدم .
چرا باید اینکار رو بکنید؟ مساله اینه. شما در انیمیشن مشخص می کنید که تا فلان مقدار بره، دیگه چرا باید بعد انیمیشن مقدار دیگری بشه؟
فرضا چرا از DiscreteDoubleKeyFrame استفاده نمی کنید؟ لزومی نداره حتما برای Completed روالی داشته باشید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
من نمیدونم شما چه کدی نوشته اید.
یه دکمه اضافه کردم (بدون تنظیم کردنِ پروپرتیِ HorizontalContentAlignment) و مقدار این پروپرتی را دیدم که Center هست .

قطعا با سخت افزار قوی تر بهتر میشه اما در کل مربوط به معماری WPF ئه و مشکل صرفا شما نیست :
اگه کارت گرافیک مهم هه ، گرافیکم ، گرافیک مجتمع پردازنده ی i5 4460 هست (گرافیک مجزا ندارم) .
میزان استفاده ی گرافیک مجتمع ام (بخش 3D اش در قسمتی که آمار مربوط به عملکرد گرافیک را در Task Manager در ویندوز 10 میده) ، از زمانی که این انیمیشن شروع شد تا زمانی که این انیمیشن تمام نشده بود ، زیرِ 5 درصد بود .

کنترل نه، ولی کمپوننت چرا، از Aspose.Cells و Aspose.Words و Saraff.Twain و ZXing.Net و Magick.NET و ...
درباره ی این کمپوننت ها بیشتر تحقیق کنم .

چرا باید اینکار رو بکنید؟ مساله اینه. شما در انیمیشن مشخص می کنید که تا فلان مقدار بره، دیگه چرا باید بعد انیمیشن مقدار دیگری بشه؟
فرضا چرا از DiscreteDoubleKeyFrame استفاده نمی کنید؟ لزومی نداره حتما برای Completed روالی داشته باشید.
خیلی ممنون استاد .
DiscreteDoubleKeyFrame استفاده نمیکنم چون به این نوع کیفریم و انیمیشن ، نیاز ندارم (SplineDoubleKeyFrame یا نهایتا LinearDoubleKeyFrame رو لازم دارم) .

درباره ی نیاز نداشتن به رویداد Completed ، درست میگید . قبلا با یه ذهنیت دیگه انیمیشن میکردم .
اما استاد ، در این کد زیر :

XML:
<Trigger Property="IsDropDownOpen" Value="True">
                                    <Setter TargetName="PART_Popup" Property="IsOpen" Value="True"/>
                                    <Trigger.EnterActions>
                                        <BeginStoryboard>
                                            <Storyboard  FillBehavior="Stop" Storyboard.TargetName="PART_Popup" Storyboard.TargetProperty="Height" Duration="0:0:2">
                                                <DoubleAnimationUsingKeyFrames>
                                                    <SplineDoubleKeyFrame KeyTime="0:0:0" Value="0" KeySpline="0.25,0.25  0.75,0.75"/>
                                                    <SplineDoubleKeyFrame KeyTime="0:0:2" Value="360" KeySpline="0.25,0.25  0.75,0.75"/>
                                                </DoubleAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </Trigger.EnterActions>
                                </Trigger>
من اگه بخوام Value ئه SplineDoubleKeyFrame را به پروپرتیِ MaxDropDownHeight ئه کمبوباکسی که توش داریم تمپلیت مینویسیم یا به پروپرتیِ MaxHeight ئه PART_Popup متصل کنم ، باید چه کدی بنویسم؟
کد :

XML:
Value="{Binding ElementName=PART_Popup, Path=MaxHeight}"
رو نوشتم اما ارور میده . templatebindign هم به پروپرتیِ MaxDropDownHeight انجام دادم اما باز هم همین ارور را میده .

و هم اینکه باز هم موقع انیمیشن کردنِ زمانی که popup بسته میشه ، چیزی انییمیشن نمیشه (در کد زیر) :

XML:
<Trigger Property="IsDropDownOpen" Value="False">
                                    <Trigger.EnterActions>
                                        <BeginStoryboard>
                                            <Storyboard FillBehavior="Stop" Storyboard.TargetName="PART_Popup" Storyboard.TargetProperty="Height" Duration="0:0:0.2">
                                                <DoubleAnimationUsingKeyFrames>
                                                    <SplineDoubleKeyFrame KeyTime="0:0:0" Value="360" KeySpline="0.25,0.25  0.75,0.75"/>
                                                    <SplineDoubleKeyFrame KeyTime="0:0:0.2" Value="0" KeySpline="0.25,0.25  0.75,0.75"/>
                                                </DoubleAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </Trigger.EnterActions>
                                    <Setter TargetName="PART_Popup" Property="IsOpen" Value="False"/>
                                </Trigger>
فکر کنم با کلیک ، کلا popup بسته میشه و نمیشه مدیریت اش کرد .
تشکر استاد :rose:
 

the_king

مدیرکل انجمن
یه دکمه اضافه کردم (بدون تنظیم کردنِ پروپرتیِ HorizontalContentAlignment) و مقدار این پروپرتی را دیدم که Center هست .
باز هم تکرار می کنم، من کدی که شما نوشته اید رو نمی بینم. در ضمن فکر هم نمی کنم شما با یک کد بتوانید نتیجه ای بگیرید. باید دو تا کد متفاوت با دو مقدار OverridesDefaultStyle ئه True / Falseرو مقایسه کنید. در ضمن حرف هاتون متناقض ئه، شما که الان به این نتیجه رسیده اید که مقدار پیشفرض اش Center ئه چرا در پست قبلی تون گفتید سمت چپ و Left رفت؟

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

خیلی ممنون استاد .
DiscreteDoubleKeyFrame استفاده نمیکنم چون به این نوع کیفریم و انیمیشن ، نیاز ندارم (SplineDoubleKeyFrame یا نهایتا LinearDoubleKeyFrame رو لازم دارم) .
DiscreteDoubleKeyFrame برای اینکه در اول، وسط یا آخر یا زمان مشخص دیگری از انیمیشن مقدار صریحی رو مشخص کنید، مثل شما که می خواهید در پایان انیمیشن مقدار مشخصی رو برای Height تعیین کنید.


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

XML:
<Trigger Property="IsDropDownOpen" Value="True">
                                    <Setter TargetName="PART_Popup" Property="IsOpen" Value="True"/>
                                    <Trigger.EnterActions>
                                        <BeginStoryboard>
                                            <Storyboard  FillBehavior="Stop" Storyboard.TargetName="PART_Popup" Storyboard.TargetProperty="Height" Duration="0:0:2">
                                                <DoubleAnimationUsingKeyFrames>
                                                    <SplineDoubleKeyFrame KeyTime="0:0:0" Value="0" KeySpline="0.25,0.25  0.75,0.75"/>
                                                    <SplineDoubleKeyFrame KeyTime="0:0:2" Value="360" KeySpline="0.25,0.25  0.75,0.75"/>
                                                </DoubleAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </Trigger.EnterActions>
                                </Trigger>
من اگه بخوام Value ئه SplineDoubleKeyFrame را به پروپرتیِ MaxDropDownHeight ئه کمبوباکسی که توش داریم تمپلیت مینویسیم یا به پروپرتیِ MaxHeight ئه PART_Popup متصل کنم ، باید چه کدی بنویسم؟
کد :

XML:
Value="{Binding ElementName=PART_Popup, Path=MaxHeight}"
رو نوشتم اما ارور میده . templatebindign هم به پروپرتیِ MaxDropDownHeight انجام دادم اما باز هم همین ارور را میده .
این صرفا یک مثال ساده است.

XML:
    <Window.Resources>
        <system:Double x:Key="MaxHeight">1000</system:Double>
    </Window.Resources>
XML:
                                <Trigger Property="IsDropDownOpen" Value="True">
                                    <Setter Property="MaxHeight" Value="{Binding ElementName=PART_Popup, Path=MaxHeight}"/>
                                    <Setter TargetName="PART_Popup" Property="IsOpen" Value="True"/>
                                    <Trigger.EnterActions>
                                        <BeginStoryboard x:Name="PopupOpen">
                                            <Storyboard FillBehavior="HoldEnd" Duration="0:0:0.5">
                                                <DoubleAnimation From="0" To="{StaticResource MaxHeight}" Storyboard.TargetName="PART_Popup" Storyboard.TargetProperty="Height" >
                                                    <DoubleAnimation.EasingFunction>
                                                        <CubicEase EasingMode="EaseInOut"/>
                                                    </DoubleAnimation.EasingFunction>
                                                </DoubleAnimation>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </Trigger.EnterActions>
                                </Trigger>
و هم اینکه باز هم موقع انیمیشن کردنِ زمانی که popup بسته میشه ، چیزی انییمیشن نمیشه (در کد زیر) :

XML:
<Trigger Property="IsDropDownOpen" Value="False">
                                    <Trigger.EnterActions>
                                        <BeginStoryboard>
                                            <Storyboard FillBehavior="Stop" Storyboard.TargetName="PART_Popup" Storyboard.TargetProperty="Height" Duration="0:0:0.2">
                                                <DoubleAnimationUsingKeyFrames>
                                                    <SplineDoubleKeyFrame KeyTime="0:0:0" Value="360" KeySpline="0.25,0.25  0.75,0.75"/>
                                                    <SplineDoubleKeyFrame KeyTime="0:0:0.2" Value="0" KeySpline="0.25,0.25  0.75,0.75"/>
                                                </DoubleAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </Trigger.EnterActions>
                                    <Setter TargetName="PART_Popup" Property="IsOpen" Value="False"/>
                                </Trigger>
فکر کنم با کلیک ، کلا popup بسته میشه و نمیشه مدیریت اش کرد .
قبلا هم گفتم که انیمیشن تون با انیمیشن Popup تداخل خواهد داشت.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
باز هم تکرار می کنم، من کدی که شما نوشته اید رو نمی بینم. در ضمن فکر هم نمی کنم شما با یک کد بتوانید نتیجه ای بگیرید. باید دو تا کد متفاوت با دو مقدار OverridesDefaultStyle ئه True / Falseرو مقایسه کنید. در ضمن حرف هاتون متناقض ئه، شما که الان به این نتیجه رسیده اید که مقدار پیشفرض اش Center ئه چرا در پست قبلی تون گفتید سمت چپ و Left رفت؟


اگر ظاهر هر دو تا کد مثل هم ئه و در هر دو Center ئه حرف شما درسته، OverridesDefaultStyle هیچ تاثیری نداره و بیخودیه و هر مقدار داشته باشه به هر حال HorizontalContentAlignment مقدار پیشفرضش Center میشه.
خیلی ممنون استاد
همونطور که در عکس زیر میبینید :

10.PNG

یه دکمه ی معمولی اضافه کردم (اونی که Content اش Button نوشته) و مقدار HorizontalContentAlignment اش هم ست نشده . در سمت راست (پنل Properties) میبینیم که مقدار این پروپرتیِ HorizontalContentAlignment ، بصورت پیش فرض روی Center هست .

اون کد دکمه ای که داده بودین و گفتم زمان طراحی ، اون Grid ئه زرد داخلی اش ، سمت چپ نبود و فقط زمان اجرا سمت چپ میرفت (دکمه ی سمت چپ در عکس بالا) بخاطر این بود که Style ای که داده بودین را من فقط پروپرتی های نظیرش را ست کرده بودم . یعنی مثلا بدون اینکه پروپرتیِ Style ای برای دکمه ام ست کنم ، مستقیما Button.ControlTemplate و پروپرتیِ OverridesDefaultStyle و Background ئه اون Button را به مقادیری که در کدتون دادید ، ست کردم که اون جور میشد . اما وقتی کلا پروپرتیِ Style اش را ست کردم ، زمان طراحی هم درست شد .
دلیلش را نمیدونم چرا .

DiscreteDoubleKeyFrame برای اینکه در اول، وسط یا آخر یا زمان مشخص دیگری از انیمیشن مقدار صریحی رو مشخص کنید، مثل شما که می خواهید در پایان انیمیشن مقدار مشخصی رو برای Height تعیین کنید.



این صرفا یک مثال ساده است.

XML:
    <Window.Resources>
        <system:Double x:Key="MaxHeight">1000</system:Double>
    </Window.Resources>
XML:
                                <Trigger Property="IsDropDownOpen" Value="True">
                                    <Setter Property="MaxHeight" Value="{Binding ElementName=PART_Popup, Path=MaxHeight}"/>
                                    <Setter TargetName="PART_Popup" Property="IsOpen" Value="True"/>
                                    <Trigger.EnterActions>
                                        <BeginStoryboard x:Name="PopupOpen">
                                            <Storyboard FillBehavior="HoldEnd" Duration="0:0:0.5">
                                                <DoubleAnimation From="0" To="{StaticResource MaxHeight}" Storyboard.TargetName="PART_Popup" Storyboard.TargetProperty="Height" >
                                                    <DoubleAnimation.EasingFunction>
                                                        <CubicEase EasingMode="EaseInOut"/>
                                                    </DoubleAnimation.EasingFunction>
                                                </DoubleAnimation>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </Trigger.EnterActions>
                                </Trigger>
خیلی ممنون استاد .
منظورتون اینه که یه Resource با نوع Double تعریف کنیم . بعد این Resource را هم در MaxHeight ئه PART_Popup و هم در Value ئه SplineDoubleKeyFrame استفاده کنیم؟

اگه آره ، مشکل اینجاست که میخوام اون Resource ای که با نوع Double تعریف میکنیم (مثل کلیدِ MaxHeight که در Window.Resources در کد بالا تعریف کردید) ، مقدارش را بصورت مستتقیم تعیین نکنیم . میخوام مقدارش را از پروپرتیِ MaxDropDownHeight ئه اون کمبوباکس (کمبوباکس ای که داریم توش تمپلیت مینویسم) ، بگیره .
وقتی Resource تعریف کنیم ، فکر نکنم بشه به پروپرتیِ MaxDropDownHeight بایند کرد . میشه؟

قبلا هم گفتم که انیمیشن تون با انیمیشن Popup تداخل خواهد داشت.
اگه منظورتون PopupAnimation="Slide" ئه PART_Popup هست ، فعلا پاک کردم .
فکر کنم مشکل اینجاست که وقتی popup باز هست ، در هر جایِ صفحه (چه داخلِ popup یا بیرونش) کلیک کنیم ، فورا popup مون بسته میشه (چه ما پروپرتیِ IsOpen اش را False کنیم یا نکنیم) و مدیریتِ اینکه خودمون با کدی تعیین کنیم که popup با کد ما بسته بشه یا نشه را نداریم .
یعنی اینکه با کلیک کردن ، مدیریت بستنِ popup ، با ما نیست .
 

the_king

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

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

یه دکمه ی معمولی اضافه کردم (اونی که Content اش Button نوشته) و مقدار HorizontalContentAlignment اش هم ست نشده . در سمت راست (پنل Properties) میبینیم که مقدار این پروپرتیِ HorizontalContentAlignment ، بصورت پیش فرض روی Center هست .
روی این دکمه Style پیشفرض داره اعمال میشه، درسته؟ که داخلش Setter ای داره برای HorizontalContentAlignment که Center اش می کنه.
می توانید کد Style پیشفرض رو در خود Visual Studio یا Blender یا سایت مایکروسافت بررسی کنید. اگر تاثیر Style پیشفرض رو ازش بگیرید می بینید که مشخصه HorizontalContentAlignment کنترل مقدار پیشفرض اش Left ئه، نه Center
اگر لازمه مجددا پست 374# رو بخونید.

خیلی ممنون استاد .
منظورتون اینه که یه Resource با نوع Double تعریف کنیم . بعد این Resource را هم در MaxHeight ئه PART_Popup و هم در Value ئه SplineDoubleKeyFrame استفاده کنیم؟
صرفا یک مثال زدم. پیشنهاد یا توصیه خاصی ندارم. اگر در اینترنت جستجو کنید راه های متفاوتی برای حل یک مساله پیدا می کنید.


اگه آره ، مشکل اینجاست که میخوام اون Resource ای که با نوع Double تعریف میکنیم (مثل کلیدِ MaxHeight که در Window.Resources در کد بالا تعریف کردید) ، مقدارش را بصورت مستتقیم تعیین نکنیم . میخوام مقدارش را از پروپرتیِ MaxDropDownHeight ئه اون کمبوباکس (کمبوباکس ای که داریم توش تمپلیت مینویسم) ، بگیره .
وقتی Resource تعریف کنیم ، فکر نکنم بشه به پروپرتیِ MaxDropDownHeight بایند کرد . میشه؟
چرا قبل از اینکه بپرسید امتحانش نمی کنید؟ اون Setter داره موقعی که IsDropDownOpen ئه True میشه به MaxHeight داخل Resources مقدار PART_Popup.MaxHeight رو میده، منبع مقدار MaxHeight اون PART_Popup رو هم که میدونید چیه. پس اون مقدار 1000 اولیه نمی مونه. امتحان کنید و ببینید وقتی برای ComboBox ئه MaxDropDownHeight مقدار مشخص می کنید، تاثیر میذاره یا نه. امتحان کردنش از تایپ کردن سوال که باید راحت تر باشه.

اگه منظورتون PopupAnimation="Slide" ئه PART_Popup هست ، فعلا پاک کردم .
کافی نیست. Popup کلاس اش کلی روال تعریف شده داره.

فکر کنم مشکل اینجاست که وقتی popup باز هست ، در هر جایِ صفحه (چه داخلِ popup یا بیرونش) کلیک کنیم ، فورا popup مون بسته میشه (چه ما پروپرتیِ IsOpen اش را False کنیم یا نکنیم) و مدیریتِ اینکه خودمون با کدی تعیین کنیم که popup با کد ما بسته بشه یا نشه را نداریم .
یعنی اینکه با کلیک کردن ، مدیریت بستنِ popup ، با ما نیست .
نه فقط WPF، پنجره های Popup ویندوز هم همینطوره، روال عادی شونه. به هر حال مشکل غیر قابل حلی نخواهد بود. باید در اینترنت دنبال مثال هایی برای این منظور باشید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
روی این دکمه Style پیشفرض داره اعمال میشه، درسته؟ که داخلش Setter ای داره برای HorizontalContentAlignment که Center اش می کنه.
می توانید کد Style پیشفرض رو در خود Visual Studio یا Blender یا سایت مایکروسافت بررسی کنید. اگر تاثیر Style پیشفرض رو ازش بگیرید می بینید که مشخصه HorizontalContentAlignment کنترل مقدار پیشفرض اش Left ئه، نه Center
اگر لازمه مجددا پست 374# رو بخونید.
خیلی ممنون استاد . :rose:
اگه منظورتون دکمه ای هست که کدش را در تصویر پست قبلی دادم ، نه . style ای روی این دکمه ، اِعمال نمیشه .

صرفا یک مثال زدم. پیشنهاد یا توصیه خاصی ندارم. اگر در اینترنت جستجو کنید راه های متفاوتی برای حل یک مساله پیدا می کنید.

چرا قبل از اینکه بپرسید امتحانش نمی کنید؟ اون Setter داره موقعی که IsDropDownOpen ئه True میشه به MaxHeight داخل Resources مقدار PART_Popup.MaxHeight رو میده، منبع مقدار MaxHeight اون PART_Popup رو هم که میدونید چیه. پس اون مقدار 1000 اولیه نمی مونه. امتحان کنید و ببینید وقتی برای ComboBox ئه MaxDropDownHeight مقدار مشخص می کنید، تاثیر میذاره یا نه. امتحان کردنش از تایپ کردن سوال که باید راحت تر باشه.
آها منظورتون اینه که اون PART_Popup.MaxHeight ، کماکان مقدارش را توسط بایندینگ از MaxDropDownHeight ئه کمبوباکس بگیره اما زمانی که اون تریگر اجرا میشه ، مقدارِ PART_Popup.MaxHeight را داخل اون Resource ای که از نوع Double بود (همون کلید MaxHeight در Resource) ، ست کنه و بعد هم برای مقدار Value ئه SplineDoubleKeyFrame ، از همون Resource ای که از نوع Double بود ، بگیریم؟
منظورتون را یه جور دیگه متوجه شده بودم .

اما با این روش هم ارور میده .
ارور ، اونجایی هست که وقتی میخوام در Setter ئه Trigger ، پروپرتیِ Property را مقدارِ myDbl (این myDbl ، نوع Double ای هست که در خط بالاتر در همین Resource ئه Grid ام تعریف کردم) بدم :

XML:
<Setter Property="myDbl" Value="{Binding ElementName=PART_Popup, Path=MaxHeight}"/>
ارور میده که شناسایی نمیشه .
با {StaticResource myDbl} و {DynamicResource myDbl} هم که کلا ارور میده .
مشکل فقط همین جاست .
این سئوال ، مهم تر از سئوال های دیگه ام هست که ان شاء ا... به نتیجه برسه .
روش های دیگه به ذهنم نمیرسه .

کافی نیست. Popup کلاس اش کلی روال تعریف شده داره.

نه فقط WPF، پنجره های Popup ویندوز هم همینطوره، روال عادی شونه. به هر حال مشکل غیر قابل حلی نخواهد بود. باید در اینترنت دنبال مثال هایی برای این منظور باشید.
یک روشی که به ذهنم رسید ، استفاده از EventTrigger و رویداد UIElement.PreviewMouseDown بود تا هر وقت والدهای کمبوباکس ای که داریم توش تمپلیت مینویسیم ، کلیکی روشون شد ، این EventTrigger را اجرا کنن که انگار عمل نمیکنه .
خیلی ممنون استاد .
 
آخرین ویرایش:

SajjadKhati

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

20.JPG

در تنظیماتش ، یه کنترلی داره که همونطور که در تصویر میبینید ، شامل عدد و همچنین متن هم میتونه باشه (عبارت "1024 MB" در تصویر بالا) .
وقتی موس روی هر یک از این عبارت میره ، شکل موس عوض میشه (شکلِ فِلِشِ چپ و راست میشه) و با کلیک و درگ به سمت چپ یا راست ، مقدارِ اون 1024 ، بیشتر یا کمتر میشه . همون عملکرد کنترل NumericUpDown خودمون را داره اما با ظاهری متفاوت .

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

the_king

مدیرکل انجمن
اگه منظورتون دکمه ای هست که کدش را در تصویر پست قبلی دادم ، نه . style ای روی این دکمه ، اِعمال نمیشه .
اگه بدون Style باشه دیگه چیزی از دکمه دیده نمیشه، اون متن Button و اون رنگ زمینه و کادر دورش از کجا میاد؟

اما با این روش هم ارور میده .
ارور ، اونجایی هست که وقتی میخوام در Setter ئه Trigger ، پروپرتیِ Property را مقدارِ myDbl (این myDbl ، نوع Double ای هست که در خط بالاتر در همین Resource ئه Grid ام تعریف کردم) بدم :

XML:
<Setter Property="myDbl" Value="{Binding ElementName=PART_Popup, Path=MaxHeight}"/>
ارور میده که شناسایی نمیشه .
با {StaticResource myDbl} و {DynamicResource myDbl} هم که کلا ارور میده .
مشکل فقط همین جاست .
این سئوال ، مهم تر از سئوال های دیگه ام هست که ان شاء ا... به نتیجه برسه .
روش های دیگه به ذهنم نمیرسه .
myDbl رو در Grid.Resources تعریف کرده اید؟ ControlTemplate.Triggers داخل Grid نیست که به Grid.Resources رجوع کنه. در ControlTemplate.Resources تعریفش کنید.
 

the_king

مدیرکل انجمن
استاد ، افترافکت (و همچنین نرم افزارهای دیگه) ، طبق شکل زیر :

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

در تنظیماتش ، یه کنترلی داره که همونطور که در تصویر میبینید ، شامل عدد و همچنین متن هم میتونه باشه (عبارت "1024 MB" در تصویر بالا) .
وقتی موس روی هر یک از این عبارت میره ، شکل موس عوض میشه (شکلِ فِلِشِ چپ و راست میشه) و با کلیک و درگ به سمت چپ یا راست ، مقدارِ اون 1024 ، بیشتر یا کمتر میشه . همون عملکرد کنترل NumericUpDown خودمون را داره اما با ظاهری متفاوت .

میخواستم بدونم اسم این کنترل ، دقیق چیه؟ تا ببینم برای دات نت ، همچین کنترلی وجود داره یا نه .
اسمش همون NumericUpDown هه؟ البته اون کنترل NumericUpDown را نمیخوام (با اون شکلی که از NumericUpDown به خاطر داریم) . کنترلی این شکلی که در تصویر میبینید ، نام خاصی نداره تا با جستجو اش ، به این شکل برسم؟
تشکر استاد .
اسم خاصی برای این کارکرد نمیشناسم، ولی هر کسی میتونه برای کنترل اش اسم بذاره.
برای نمونه numeric slider control در سرویس جستجوی تصویر گوگل جستجو کنید.
شکل و عملکرد کنترل رو عوض می کنید و یک Extended یا Pro یا Ultimate و ... به نامش اضافه می کنید.
اما به هر حال تغییر شکل نشانگر ماوس یا تغییر مقدار با درگ کردن کار سختی نیست.
 

SajjadKhati

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


myDbl رو در Grid.Resources تعریف کرده اید؟ ControlTemplate.Triggers داخل Grid نیست که به Grid.Resources رجوع کنه. در ControlTemplate.Resources تعریفش کنید.
ممنون .
بازم همون ارور رو میده که نمیتونه شناسایی بشه :

XML:
            <!-- SimpleComboBox -->
            <Style x:Key="{x:Type ComboBox}" TargetType="{x:Type ComboBox}">
                <Setter Property="SnapsToDevicePixels" Value="False"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ComboBox}">
                        
                            <ControlTemplate.Resources>
                                <System:Double x:Key="myDbl">50</System:Double>
                            </ControlTemplate.Resources>
                        
                            <Grid>
                                <!--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" 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"/>
                                    <Setter Property="myDbl" Value="{Binding ElementName=PART_Popup, Path=MaxHeight}"/>
                                    <Trigger.EnterActions>
                                        <BeginStoryboard>
                                            <Storyboard  FillBehavior="Stop" Storyboard.TargetName="PART_EditableTextBox" Storyboard.TargetProperty="Height" Duration="0:0:2">
                                                <DoubleAnimationUsingKeyFrames>
                                                    <SplineDoubleKeyFrame KeyTime="0:0:0" Value="0" KeySpline="0.25,0.25  0.75,0.75"/>
                                                    <SplineDoubleKeyFrame KeyTime="0:0:2" Value="{StaticResource myDbl}" KeySpline="0.25,0.25  0.75,0.75"/>
                                                </DoubleAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </Trigger.EnterActions>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
ارورش :
The member "myDbl" is not recognized or is not accessible.

در همون خطِ Setter Property="myDbl" ، این ارور را میده .
اگه این روش نمیشه ، راهکارهای دیگه ، چی هستن؟ بی زحمت لینک میدین اگه لازم شد؟


اسم خاصی برای این کارکرد نمیشناسم، ولی هر کسی میتونه برای کنترل اش اسم بذاره.
برای نمونه numeric slider control در سرویس جستجوی تصویر گوگل جستجو کنید.
شکل و عملکرد کنترل رو عوض می کنید و یک Extended یا Pro یا Ultimate و ... به نامش اضافه می کنید.
اما به هر حال تغییر شکل نشانگر ماوس یا تغییر مقدار با درگ کردن کار سختی نیست.
خیلی ممنون استاد .
اگه خودمون همچین کنترلی را بخوایم در wpf بسازیم ، بهتره که از کلاس user control ارث بری کنیم یا اینکه خودمون یه custom control بسازیم و مثلا از کلاس control یا ContentControl ارث بری کنیم؟
کلا برای پیاده سازی همچین کنترلی ، از چه کلاسی بهتره که ارث بری کنیم؟

البته منظورم نیست که حتما چنین کنترلی را میسازم . ولی میخوام بدونم که استانداردش اینه که از چه کلاسی ارث بری کنیم؟
 
آخرین ویرایش:

the_king

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

XML:
            <!-- SimpleComboBox -->
            <Style x:Key="{x:Type ComboBox}" TargetType="{x:Type ComboBox}">
                <Setter Property="SnapsToDevicePixels" Value="False"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ComboBox}">
                       
                            <ControlTemplate.Resources>
                                <System:Double x:Key="myDbl">50</System:Double>
                            </ControlTemplate.Resources>
                       
                            <Grid>
                                <!--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" 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"/>
                                    <Setter Property="myDbl" Value="{Binding ElementName=PART_Popup, Path=MaxHeight}"/>
                                    <Trigger.EnterActions>
                                        <BeginStoryboard>
                                            <Storyboard  FillBehavior="Stop" Storyboard.TargetName="PART_EditableTextBox" Storyboard.TargetProperty="Height" Duration="0:0:2">
                                                <DoubleAnimationUsingKeyFrames>
                                                    <SplineDoubleKeyFrame KeyTime="0:0:0" Value="0" KeySpline="0.25,0.25  0.75,0.75"/>
                                                    <SplineDoubleKeyFrame KeyTime="0:0:2" Value="{StaticResource myDbl}" KeySpline="0.25,0.25  0.75,0.75"/>
                                                </DoubleAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </Trigger.EnterActions>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
ارورش :
The member "myDbl" is not recognized or is not accessible.

در همون خطِ Setter Property="myDbl" ، این ارور را میده .
الان دو تا ایراد عمده داره. اول اینکه خطا میده که چرا مشخصه ای به نام myDbl وجود نداره. بی دلیل از MaxHeight استفاده نکردم. دوم اینکه انیمیشن درستی ندارید. بین PART_EditableTextBox و MaxHeight / MaxDropDownHeight ارتباط منطقی ای وجود داره که PART_EditableTextBox.Height رو تغییر می دهید؟

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

خیلی ممنون استاد .
اگه خودمون همچین کنترلی را بخوایم در wpf بسازیم ، بهتره که از کلاس user control ارث بری کنیم یا اینکه خودمون یه custom control بسازیم و مثلا از کلاس control یا ContentControl ارث بری کنیم؟
کلا برای پیاده سازی همچین کنترلی ، از چه کلاسی بهتره که ارث بری کنیم؟
UserControl برای ساختن هر کنترل عمومی که میتونه ترکیب چند کنترل هم باشه مناسب ئه، اما مشخصه ها و روال اختصاصی هیچ کنترل خاصی رو نداره، خیلی عمومی است. نتیجه اش اینه که هر چقدر بخواهید به ویژگی های یک کنترل خاصی نزدیکش کنید زحمت کد نویسی بیشتری خواهید داشت.
فرضا اگر بخواهید یک ComboBox اختصاصی طراحی کنید، تبدیل کردن UserControl به ComboBox سخت میشه چون باید برای همه مشخصه های ComboBox ئه کد بنویسید، چیزهایی که UserControl نداره. پس بهتره کلاس ای رو برای وراثت انتخاب کنید که بیشترین مشخصه ها و رفتاری که لازم دارید رو از قبل داره تا زحمت کد نویسی کمتری داشته باشید.

البته منظورم نیست که حتما چنین کنترلی را میسازم . ولی میخوام بدونم که استانداردش اینه که از چه کلاسی ارث بری کنیم؟
هر چقدر کلاس پایه به مشخصات اون کنترل مورد نظرتون نزدیکتر باشه بهتر ئه، هم زحمت کد نویسی کمتر میشه و هم احتمال باگ در کد نویسی کاهش پیدا می کنه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
الان دو تا ایراد عمده داره. اول اینکه خطا میده که چرا مشخصه ای به نام myDbl وجود نداره. بی دلیل از MaxHeight استفاده نکردم. دوم اینکه انیمیشن درستی ندارید. بین PART_EditableTextBox و MaxHeight / MaxDropDownHeight ارتباط منطقی ای وجود داره که PART_EditableTextBox.Height رو تغییر می دهید؟


سوال خوبیه، ولی کسی که نیاز به پاسخش داره باید تحقیق کنه. من که دنبال راهکار ها نیستم که وقت صرف جستجو شون کنم.
خیلی ممنون استاد . :rose:
بله . اشتباها نام PART_EditableTextBox و PART_Popup را اشتباه نوشتم .
اما من رابطه ی بین نام myDbl و تغییر نامش به MaxHeight را متوجه نشدم .
تغییر نام دادم . ارور نمیده اما عملی هم که من لازم دارم را انجام نمیده . الان مگه در کد زیر :

XML:
            <!-- SimpleComboBox -->
            <Style x:Key="{x:Type ComboBox}" TargetType="{x:Type ComboBox}">
                <Setter Property="SnapsToDevicePixels" Value="False"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ComboBox}">
                            
                            <ControlTemplate.Resources>
                                <System:Double x:Key="MaxHeight">50</System:Double>
                            </ControlTemplate.Resources>
                            
                            <Grid>
                                <!--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" 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"/>
                                    <Setter Property="MaxHeight" Value="{Binding ElementName=PART_Popup, Path=MaxHeight}"/>
                                    <Trigger.EnterActions>
                                        <BeginStoryboard>
                                            <Storyboard  FillBehavior="Stop" Storyboard.TargetName="PART_Popup" Storyboard.TargetProperty="Height" Duration="0:0:2">
                                                <DoubleAnimationUsingKeyFrames>
                                                    <SplineDoubleKeyFrame KeyTime="0:0:0" Value="0" KeySpline="0.25,0.25  0.75,0.75"/>
                                                    <SplineDoubleKeyFrame KeyTime="0:0:2" Value="{StaticResource MaxHeight}" KeySpline="0.25,0.25  0.75,0.75"/>
                                                </DoubleAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </Trigger.EnterActions>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Styl
وقتی کد :

XML:
<Setter Property="MaxHeight" Value="{Binding ElementName=PART_Popup, Path=MaxHeight}"/>
اجرا میشه ، مگه مقدارِ PART_Popup.MaxHeight را توی پروپرتیِ MaxHeight ئه اون کمبوباکس مون ست نمیکنه؟
اگه نه ، پس چی کار میکنه؟
اگه آره ، خوب ما که لازم داریم مقدارِ موجود در Resource که نام کلیدش MaxHeight هست را تغییر بده . کاری با پروپرتیِ MaxHeight ئه کمبوباکس نداریم .
من که دقیق متوجه نشدم .

استاد ، منظورم این بود که یه متن ای برای جستجو یا لینکی که به این مبحث ربط داشته باشه رو اگه میشه بدین . مثلا بگین چه عبارت انگلیسی را برای این کار جستجو کنم؟ (چند مورد را زدم ولی نتیجه ی دلخواهم نبود) .

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


هر چقدر کلاس پایه به مشخصات اون کنترل مورد نظرتون نزدیکتر باشه بهتر ئه، هم زحمت کد نویسی کمتر میشه و هم احتمال باگ در کد نویسی کاهش پیدا می کنه.
بله میدونم . اما میخوام بدونم که چه کلاسی برای اون کنترلی که در افترافکت نشون داده بودم را اگه بخوام طراحی کنم ، بهترین کلاس برای ارث بری هست (که یشترین مشخصه ها و رفتاری که برای این کنترا لازم دارم رو داشته باشه تا کمترین کد رو برای این کار بنویسم)؟
ContentControl خوب نیست؟
ممنون استاد .
 

the_king

مدیرکل انجمن
خیلی ممنون استاد . :rose:
بله . اشتباها نام PART_EditableTextBox و PART_Popup را اشتباه نوشتم .
اما من رابطه ی بین نام myDbl و تغییر نامش به MaxHeight را متوجه نشدم .
تغییر نام دادم . ارور نمیده اما عملی هم که من لازم دارم را انجام نمیده . الان مگه در کد زیر :

XML:
            <!-- SimpleComboBox -->
            <Style x:Key="{x:Type ComboBox}" TargetType="{x:Type ComboBox}">
                <Setter Property="SnapsToDevicePixels" Value="False"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ComboBox}">
                          
                            <ControlTemplate.Resources>
                                <System:Double x:Key="MaxHeight">50</System:Double>
                            </ControlTemplate.Resources>
                          
                            <Grid>
                                <!--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" 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"/>
                                    <Setter Property="MaxHeight" Value="{Binding ElementName=PART_Popup, Path=MaxHeight}"/>
                                    <Trigger.EnterActions>
                                        <BeginStoryboard>
                                            <Storyboard  FillBehavior="Stop" Storyboard.TargetName="PART_Popup" Storyboard.TargetProperty="Height" Duration="0:0:2">
                                                <DoubleAnimationUsingKeyFrames>
                                                    <SplineDoubleKeyFrame KeyTime="0:0:0" Value="0" KeySpline="0.25,0.25  0.75,0.75"/>
                                                    <SplineDoubleKeyFrame KeyTime="0:0:2" Value="{StaticResource MaxHeight}" KeySpline="0.25,0.25  0.75,0.75"/>
                                                </DoubleAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </Trigger.EnterActions>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Styl
وقتی کد :

XML:
<Setter Property="MaxHeight" Value="{Binding ElementName=PART_Popup, Path=MaxHeight}"/>
اجرا میشه ، مگه مقدارِ PART_Popup.MaxHeight را توی پروپرتیِ MaxHeight ئه اون کمبوباکس مون ست نمیکنه؟
اگه نه ، پس چی کار میکنه؟
اگه آره ، خوب ما که لازم داریم مقدارِ موجود در Resource که نام کلیدش MaxHeight هست را تغییر بده . کاری با پروپرتیِ MaxHeight ئه کمبوباکس نداریم .
من که دقیق متوجه نشدم .
اشتباه از من بود، هم توضیح خوبی ندادم و هم حداقل باید از نام بهتری برای MaxHeight استفاده می کردم تا تشابه اسامی گمراه تون نکنه. MaxHeight ای که من تعریف کردم صرفا یک مقدار اولیه برای انیمیشن ئه، که فرضا Height تا حداکثر 1000 پیش بره. از اونجایی که Height نمیتونه از مقدار مشخصه MaxHeight بیشتر بشه Height در انیمیشن به مقدار مشخصه MaxHeight محدود میشه.
همونطور که گفتم هدفم صرفا ارائه یک مثال ساده برای موضوع سوال شما بود، نه اینکه یک قاعده کلی باشه که بخواهید ازش نتیجه گیری کنید.

استاد ، منظورم این بود که یه متن ای برای جستجو یا لینکی که به این مبحث ربط داشته باشه رو اگه میشه بدین . مثلا بگین چه عبارت انگلیسی را برای این کار جستجو کنم؟ (چند مورد را زدم ولی نتیجه ی دلخواهم نبود) .
مثلا
wpf passing data in xaml
wpf custom binding extension
wpf custom popup animation
و هر پیام خطایی که دریافت می کنید.

بله میدونم . اما میخوام بدونم که چه کلاسی برای اون کنترلی که در افترافکت نشون داده بودم را اگه بخوام طراحی کنم ، بهترین کلاس برای ارث بری هست (که یشترین مشخصه ها و رفتاری که برای این کنترا لازم دارم رو داشته باشه تا کمترین کد رو برای این کار بنویسم)؟
ContentControl خوب نیست؟
ContentControl چه ویژگی هایی خاصی داره که مناسب کنترل شما است؟ وقتی میخواهید مشخص کنید که این کنترل قراره در محدوده 10 الی 100 مقدار بگیره و نشون بده، با کدوم مشخصه های ContentControl بازه رو مشخص می کنید؟ بهتره کلاسی که رو انتخاب کنید که لااقل مشخصه هایی برای تعیین بازه (مقدار حداقل و حداکثر) و ... داشته باشه. مثلا Slider یا RangeBase.
 

SajjadKhati

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


مثلا
wpf passing data in xaml
wpf custom binding extension
wpf custom popup animation
و هر پیام خطایی که دریافت می کنید.
سلامی مجدد
خیلی ممنون استاد . خواهش میشود استاد . توضیح تون هم خوب بود :rose:
استاد ، از روش قبلی که مستقیما به PART_Popup.MaxHeight بایند کرده بودیم (بدون استفاده از قضیه ی Resource) که کدش میشد :

XML:
<SplineDoubleKeyFrame KeyTime="0:0:1" Value="{Binding ElementName=PART_Popup, Path=MaxHeight}" KeySpline="0.25,0.25  0.75,0.75"/>
و زمان اجرا ، ارور زیر را میداد :

کد:
InvalidOperationException: Cannot freeze this Storyboard timeline tree for use across threads.
و میگه نمیتونه اون Storyboard را فریز کنه تا در چندین نخ (نخ های دیگه) ازش استفاده بشه ، را جستجو کردم و به لینک های زیر رسیدم :


و


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

XML:
<ScrollViewer.Tag>
            <sys:Double>0.0</sys:Double>
        </ScrollViewer.Tag>
        <ScrollViewer.Height>
            <MultiBinding Converter="{StaticResource multiplyConverter}">
               <Binding Path="ActualHeight" ElementName="ExpanderContent"/>
               <Binding Path="Tag" RelativeSource="{RelativeSource Self}" />
            </MultiBinding>
        </ScrollViewer.Height>
و بعد هم پروپرتیِ Tag را برای انیمیشن استفاده کردن (که کلا خوب متوجه نشدم چی کار کردن) .

روش DynamicResource هم انگار جستجو کرده بودم (که بکار برده بودیم)، ممکنه همین مشکلات را داشته باشه (StaticResource زیاد به دردم نمیخوره چون برنامه نویس ممکنه مقدار MaxDropDownHeight ئه کمبوباکس را زمان اجرا ، چندین بار تغییر هم بده) .

به هر حال روش آسونی انگار به نظر نمیرسه که برای این کار وجود داشته باشه .


ContentControl چه ویژگی هایی خاصی داره که مناسب کنترل شما است؟ وقتی میخواهید مشخص کنید که این کنترل قراره در محدوده 10 الی 100 مقدار بگیره و نشون بده، با کدوم مشخصه های ContentControl بازه رو مشخص می کنید؟ بهتره کلاسی که رو انتخاب کنید که لااقل مشخصه هایی برای تعیین بازه (مقدار حداقل و حداکثر) و ... داشته باشه. مثلا Slider یا RangeBase.
چه فکر خوبی استاد .
الان اگه برای کنترلِ Slider ، تمپلیت بنویسم ، میشه کنترل Slider را شبیه به اون کنترلی که در افترافکت نشون دادم ، درآورد . درسته؟
خیلی ممنون استاد .
 

the_king

مدیرکل انجمن
سلامی مجدد
خیلی ممنون استاد . خواهش میشود استاد . توضیح تون هم خوب بود :rose:
استاد ، از روش قبلی که مستقیما به PART_Popup.MaxHeight بایند کرده بودیم (بدون استفاده از قضیه ی Resource) که کدش میشد :

XML:
<SplineDoubleKeyFrame KeyTime="0:0:1" Value="{Binding ElementName=PART_Popup, Path=MaxHeight}" KeySpline="0.25,0.25  0.75,0.75"/>
و زمان اجرا ، ارور زیر را میداد :

کد:
InvalidOperationException: Cannot freeze this Storyboard timeline tree for use across threads.
و میگه نمیتونه اون Storyboard را فریز کنه تا در چندین نخ (نخ های دیگه) ازش استفاده بشه ، را جستجو کردم و به لینک های زیر رسیدم :


و


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

XML:
<ScrollViewer.Tag>
            <sys:Double>0.0</sys:Double>
        </ScrollViewer.Tag>
        <ScrollViewer.Height>
            <MultiBinding Converter="{StaticResource multiplyConverter}">
               <Binding Path="ActualHeight" ElementName="ExpanderContent"/>
               <Binding Path="Tag" RelativeSource="{RelativeSource Self}" />
            </MultiBinding>
        </ScrollViewer.Height>
و بعد هم پروپرتیِ Tag را برای انیمیشن استفاده کردن (که کلا خوب متوجه نشدم چی کار کردن) .

روش DynamicResource هم انگار جستجو کرده بودم (که بکار برده بودیم)، ممکنه همین مشکلات را داشته باشه (StaticResource زیاد به دردم نمیخوره چون برنامه نویس ممکنه مقدار MaxDropDownHeight ئه کمبوباکس را زمان اجرا ، چندین بار تغییر هم بده) .

به هر حال روش آسونی انگار به نظر نمیرسه که برای این کار وجود داشته باشه .
یک مثال بزنم؟ این کلاس MyClass یک مشخصه الحاقی داره به نام MyDbl
C#:
    public class MyClass
    {
        public static readonly DependencyProperty MyDblProperty
            = DependencyProperty.RegisterAttached("MyDbl", typeof(double), typeof(MyClass)
                , new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender));

        public static void SetMyDbl(UIElement element, double value)
        {
            element.SetValue(MyDblProperty, value);
        }

        public static double GetMyDbl(UIElement element)
        {
            return (double)element.GetValue(MyDblProperty);
        }
    }
نوع double و مقدار پیشفرض اش هم که 0.0 ئه.

که نحوه دسترسی به مشخصه های الحاقی هم در XAML قاعده خودش رو داره :
XML:
        <Button Width="200" Height="50" HorizontalAlignment="Center" VerticalAlignment="Center" Click="Button_Click" Content="{Binding Path=(local:MyClass.MyDbl), RelativeSource={RelativeSource Self}}">
            <Button.Style>
                <Style TargetType="Button">
                    <Style.Setters>
                        <Setter Property="local:MyClass.MyDbl" Value="50"/>
                    </Style.Setters>
                    <Style.Triggers>
                        <EventTrigger RoutedEvent="Click">
                            <BeginStoryboard>
                                <Storyboard Storyboard.TargetProperty="(local:MyClass.MyDbl)" Duration="0:0:2" FillBehavior="Stop">
                                    <DoubleAnimation From="0" To="100" Duration="0:0:2"/>
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="local:MyClass.MyDbl" Value="123.0"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
        </Button>
فراموش نکنید که موقع دریافت مقدار مشخصه الحاقی که static ئه باید بگید مقدار اون مشخصه رو در کدوم المنت میخواهید :
C#:
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show(MyClass.GetMyDbl((Button)sender).ToString());
        }
چه فکر خوبی استاد .
الان اگه برای کنترلِ Slider ، تمپلیت بنویسم ، میشه کنترل Slider را شبیه به اون کنترلی که در افترافکت نشون دادم ، درآورد . درسته؟
خیلی ممنون استاد .
هر ظاهری رو می توانید به یک کنترل بدهید، فقط اگر دیدید با حذف کردن یک المنت کلیدی خاص خطایی رخ داد یا مشکلی بوجود اومد، معنی اش اینه که در کلاس به اون المنت ارجاع داده شده و باید اون المنت خاص رو در توصیف Template اش داشته باشید، گر چه ممکنه Hidden اش کرده باشید تا نقشی در ظاهر دلخواه شما نداشته باشه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
یک مثال بزنم؟ این کلاس MyClass یک مشخصه الحاقی داره به نام MyDbl
C#:
    public class MyClass
    {
        public static readonly DependencyProperty MyDblProperty
            = DependencyProperty.RegisterAttached("MyDbl", typeof(double), typeof(MyClass)
                , new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender));

        public static void SetMyDbl(UIElement element, double value)
        {
            element.SetValue(MyDblProperty, value);
        }

        public static double GetMyDbl(UIElement element)
        {
            return (double)element.GetValue(MyDblProperty);
        }
    }
نوع double و مقدار پیشفرض اش هم که 0.0 ئه.

که نحوه دسترسی به مشخصه های الحاقی هم در XAML قاعده خودش رو داره :
XML:
        <Button Width="200" Height="50" HorizontalAlignment="Center" VerticalAlignment="Center" Click="Button_Click" Content="{Binding Path=(local:MyClass.MyDbl), RelativeSource={RelativeSource Self}}">
            <Button.Style>
                <Style TargetType="Button">
                    <Style.Setters>
                        <Setter Property="local:MyClass.MyDbl" Value="50"/>
                    </Style.Setters>
                    <Style.Triggers>
                        <EventTrigger RoutedEvent="Click">
                            <BeginStoryboard>
                                <Storyboard Storyboard.TargetProperty="(local:MyClass.MyDbl)" Duration="0:0:2" FillBehavior="Stop">
                                    <DoubleAnimation From="0" To="100" Duration="0:0:2"/>
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="local:MyClass.MyDbl" Value="123.0"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
        </Button>
فراموش نکنید که موقع دریافت مقدار مشخصه الحاقی که static ئه باید بگید مقدار اون مشخصه رو در کدوم المنت میخواهید :
C#:
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show(MyClass.GetMyDbl((Button)sender).ToString());
        }
خیلی ممنون استاد :rose:
آها ، یعنی با ساختنِ Attached Property ، میتونیم داخلِ این نوع پروپرتی (داخل Attached Property) ، مقدار سِت کنیم؟
باز این روش ، خیلی آسون تر از اون روشی هست که من پیدا کرده بودم (در پست قبل) . البته یه مشکل کوچیکش اینه که از کدهای سی شارپ هم استفاده میشه که حالا میشه نادیده اش گرفت .
ممنون استاد .


هر ظاهری رو می توانید به یک کنترل بدهید، فقط اگر دیدید با حذف کردن یک المنت کلیدی خاص خطایی رخ داد یا مشکلی بوجود اومد، معنی اش اینه که در کلاس به اون المنت ارجاع داده شده و باید اون المنت خاص رو در توصیف Template اش داشته باشید، گر چه ممکنه Hidden اش کرده باشید تا نقشی در ظاهر دلخواه شما نداشته باشه.
استاد فعلا تصمیم گرفتم از کنترل xceed.wpf.toolkit استفاده کنم :


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

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

استاد ، تمپلیت ای که برای همین کنترل (DoubleUpDown) نوشتم و در این پست پیوست میکنم ، دو تا مشکل داره :

XML:
        <ToolKit:DoubleUpDown Name="numUpDown" Style="{StaticResource DoubleUpDownStyle}" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="20,20,0,0" Width="100" Height="36" Background="#FF5F5F5F" Value="10" BorderBrush="White" Foreground="White" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
اول اینکه وقتی در قسمت Trigger ئه اون تمپلیتِ DoubleUpDownStyle ، برای IsFocused ، اون تریگر را مینویسم ، زمانی که روی اون کنترل فوکوس انجام میشه ، اجرا نمیشه . اما اگه برای کنترل TextBox ای که داخلِ اون تمپلیت هست ، شرط بذارم ، اجرا میشه . مشکل تریگر در تمپلیت چیه که وقتی روی IsFocused ئه کنترل DoubleUpDown شرط میذارم ، اجرا نمیشه؟

دوم اینکه وقتی که از همین کنترل DoubleUpDown شی بسازید (منظورم همین داخلxaml هست) ، اگه این تمپلیت را بکار نبرید ، زمان اجرای برنامه ، وقتی که داخل بخشِ TextBox ئه DoubleUpDown کلیک کنید (یا کلا فوکوسی روش انجام بشه) و بعد دکمه ی بالا (فِلِش بالا) یا دکمه ی پایین (فِلِشِ پایین) در کیبرد رو بزنید ، اعداد کم یا زیاد میشن اما وقتی این تمپلیت را بکار ببرید ، این قابلیت رو دیگه نداره .
مشکل این از کجاست؟

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

پیوست ها

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

بالا