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

SajjadKhati

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

کد:
                <Rectangle Name="myRectangle" Fill="DarkOrange" Margin="425,316,1067,453">
                    <Rectangle.Triggers>
                        <EventTrigger RoutedEvent="Rectangle.Loaded">
                            <EventTrigger.Actions>
                                <BeginStoryboard>
                                    <BeginStoryboard.Storyboard>
                                        <Storyboard
                                            Storyboard.TargetName="myRectangle"
                                            Storyboard.TargetProperty="Opacity"
                                             Duration="0:0:4"
                                            AutoReverse="True" RepeatBehavior="Forever">
                                            <Storyboard.Children>
                                                <DoubleAnimation From="0.0" To="1.0" />
                                            </Storyboard.Children>
                                        </Storyboard>
                                    </BeginStoryboard.Storyboard>
                                </BeginStoryboard>
                            </EventTrigger.Actions>
                        </EventTrigger>
                    </Rectangle.Triggers>
                </Rectangle>

من زمان را 4 ثانیه تعیین کردم تا بعد از 4 ثانیه ، انیمیشن معکوس (revers) بشه اما تقریبا 2 برابر ، یعنی هر 8 ثانیه ، معکوس میشه . چرا؟
 

the_king

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

کد:
                <Rectangle Name="myRectangle" Fill="DarkOrange" Margin="425,316,1067,453">
                    <Rectangle.Triggers>
                        <EventTrigger RoutedEvent="Rectangle.Loaded">
                            <EventTrigger.Actions>
                                <BeginStoryboard>
                                    <BeginStoryboard.Storyboard>
                                        <Storyboard
                                            Storyboard.TargetName="myRectangle"
                                            Storyboard.TargetProperty="Opacity"
                                             Duration="0:0:4"
                                            AutoReverse="True" RepeatBehavior="Forever">
                                            <Storyboard.Children>
                                                <DoubleAnimation From="0.0" To="1.0" />
                                            </Storyboard.Children>
                                        </Storyboard>
                                    </BeginStoryboard.Storyboard>
                                </BeginStoryboard>
                            </EventTrigger.Actions>
                        </EventTrigger>
                    </Rectangle.Triggers>
                </Rectangle>

من زمان را 4 ثانیه تعیین کردم تا بعد از 4 ثانیه ، انیمیشن معکوس (revers) بشه اما تقریبا 2 برابر ، یعنی هر 8 ثانیه ، معکوس میشه . چرا؟
شما یک Storyboard طراحی کرده اید که 4 ثانیه طول بکشه و بعد معکوس بشه، یعنی جمعا 8 ثانیه تا تکرار مجدد. یک DoubleAnimation هم برایش تعریف کرده اید که Duration پیشفرض یک ثانیه ای داره و بعد یک ثانیه دیگه کاری برای انجام نداره.
ثانیه 0 - یک ثانیه انیمیشن اجرا میشه
ثانیه 1 - سه ثانیه بیکار ئه.
ثانیه 4 - بعد 4 ثانیه Storyboard تموم شده و روال معکوس میشه و سه ثانیه بیکار ئه.
ثانیه 7 - یک ثانیه آخر هم انیمیشن معکوس اجرا میشه و 8 ثانیه تموم میشه.
ثانیه 8 - تمام
کد:
        <Rectangle Name="myRectangle" Fill="DarkOrange">
            <Rectangle.Triggers>
                <EventTrigger RoutedEvent="Rectangle.Loaded">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <BeginStoryboard.Storyboard>
                                <Storyboard
                                    Storyboard.TargetName="myRectangle"
                                    Storyboard.TargetProperty="Opacity"
                                    Duration="0:0:4"
                                    AutoReverse="True" RepeatBehavior="Forever">
                                    <Storyboard.Children>
                                        <DoubleAnimation From="0.0" To="1.0"/>
                                        <StringAnimationUsingKeyFrames Storyboard.TargetName="MyText" Storyboard.TargetProperty="Text" FillBehavior="HoldEnd">
                                            <DiscreteStringKeyFrame Value="0%" KeyTime="0:0:0" />
                                            <DiscreteStringKeyFrame Value="25%" KeyTime="0:0:1" />
                                            <DiscreteStringKeyFrame Value="50%" KeyTime="0:0:2" />
                                            <DiscreteStringKeyFrame Value="75%" KeyTime="0:0:3" />
                                            <DiscreteStringKeyFrame Value="100%" KeyTime="0:0:3.95" />
                                        </StringAnimationUsingKeyFrames>
                                    </Storyboard.Children>
                                </Storyboard>
                            </BeginStoryboard.Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
            </Rectangle.Triggers>
        </Rectangle>
        <TextBlock Name="MyText" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="30"/>

ارتباط شون به هم چیه؟
خوب در attributes اش که مشخص کرده بودیم ، این تعیین مقدارش ، برای زمان طراحی استفاده بشه اما مقداری از اون پروپرتی ای که در style مشخص کردیم ، زمانی که اون trigger اتفاق افتاد ، همون مقدار بشه .
دقیقا تناقض این دو را متوجه نشدم که برای چی هستن . علی الظاهر نباید تناقضی با هم داشته باشن .
Style یک قالب کلی ئه، ولی اون چیزی که برای خود المنت مشخص میکنید، اختصاصی ئه، توصیف اختصاصی بر توصیف کلی اولویت داره. اگر با HTML و CSS آشنایی داشته باشید میدونید که در CSS هم همینطور ئه، Style مشخص شده برای المنت با مواردی که اختصاصا برای المنت مشخص میشه باطل میشن.

آیا در اینجا میشه گفت که شی Storyboard ، شبیه کمپوزیشن اصلی عمل میکنه (یعنی بستر اصلی انیمیشن هست) و اشیاء های TimeLine ای که در پروپرتیِ Children ئه Storyboard قرار میدیم (مثل DoubleAnimation و StringAnimation و Int32Animation و ...) ، شبیه لایه هایی که درون کمپوزیشن اصلی در افترافکت قرار میدیم ، هستن؟
نمیدونم، با افترافکت آشنایی ندارم اما Storyboard کلا فقط برای مدیریت timeline ئه.
 

SajjadKhati

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

Animation Tips and Tricks - WPF

در مثال زیری که زد :

کد:
        private void StoryboardC_Completed(object sender, EventArgs e)
        {
            Storyboard translationAnimationStoryboard = (Storyboard)this.Resources["TranslationAnimationStoryboardResource"];
            translationAnimationStoryboard.Begin(this);
        }

خط اول ، ارور null reference میده .
کد زیر را هم که گفته بود :

کد:
<Page.Resources>
  <Storyboard x:Key="TranslationAnimationStoryboardResource">
    <DoubleAnimation
      Storyboard.TargetName="MyTranslateTransform"
      Storyboard.TargetProperty="X"
      To="500" Duration="0:0:5" />
  </Storyboard>
</Page.Resources>

در Resource ئه مربوط به کنترل Grid تعریف کردم . یعنی کد کلی ، اینه :

کد:
<Window x:Class="WPF_Practice.WinAnimation"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPF_Practice"
        mc:Ignorable="d"
        Title="WinAnimation" Height="768" Width="1366">

    <Grid x:Name="myGrid1" Background="#FFC9C9C9">
        <Grid.Resources>
            <Storyboard x:Key="TranslationAnimationStoryboardResource">
                <DoubleAnimation
                  Storyboard.TargetName="MyTranslateTransform"
                  Storyboard.TargetProperty="X"
                  To="500" Duration="0:0:5" />
            </Storyboard>
        </Grid.Resources>
       
       
        <Grid.Children>



            <Canvas Width="600" Height="200" Margin="131,10,627,527" Background="#FFB9B9B9" >
                <Rectangle
                    Canvas.Top="50" Canvas.Left="0"
                    Width="50" Height="50" Fill="Red">
                    <Rectangle.RenderTransform>
                        <TranslateTransform
                            x:Name="MyTranslateTransform"
                            X="0" Y="50" />
                    </Rectangle.RenderTransform>
                </Rectangle>


                <Button Name="btnTest_2" Content="Start Storyboard B1"  Width="120" Height="50" HorizontalAlignment="Left" VerticalAlignment="Top" >
                    <Button.Triggers>
                        <EventTrigger RoutedEvent="Button.Click">
                            <BeginStoryboard>
                                <Storyboard x:Name="B1">
                                    <DoubleAnimation
                                    Storyboard.TargetName="MyTranslateTransform"
                                    Storyboard.TargetProperty="X"
                                    From="0" To="200" Duration="0:0:5"
                                    FillBehavior="Stop"
                                    />
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger>
                    </Button.Triggers>
                </Button>

                <Button Content="Start Storyboard B2" Width="120" Height="50" Canvas.Left="140">
                    <Button.Triggers>
                        <EventTrigger RoutedEvent="Button.Click">
                            <BeginStoryboard>
                                <Storyboard x:Name="B2">
                                    <DoubleAnimation
                                    Storyboard.TargetName="MyTranslateTransform"
                                    Storyboard.TargetProperty="X"
                                    To="500" Duration="0:0:5"
                                    FillBehavior="Stop" />
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger>
                    </Button.Triggers>
                </Button>

                <Button Content="Start Storyboard C" Width="120" Height="50" Canvas.Left="280">
                    <Button.Triggers>
                        <EventTrigger RoutedEvent="Button.Click">
                            <BeginStoryboard>
                                <Storyboard Completed="StoryboardC_Completed">
                                    <DoubleAnimation
                                    Storyboard.TargetName="MyTranslateTransform"
                                    Storyboard.TargetProperty="X"
                                    From="0" To="500" Duration="0:0:5"
                                    FillBehavior="Stop" />
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger>
                    </Button.Triggers>
                </Button>

               
            </Canvas>






        </Grid.Children>
    </Grid>
</Window>

در کد اول ، متد Begin در خط دوم ، وقتی شی this را بهش دادیم ، یعنی شیِ window جاری مون را انیمیشن میکنه؟ اگه آره ، چه پروپرتی ای از شیِ window مون را انیمیت میکنه؟

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

همچنین بخش FillBehavior.Stop Doesn't Work as Expected را متوجه نشدم منظورش چیه؟
منظورم بخش FillBehavior="Stop" and HandoffBehavior with Multiple Animations نیست .

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

the_king

مدیرکل انجمن
خط اول ، ارور null reference میده .
اگه کد رو برای Page بکار نمی برید بجای <Page.Resources> باید از مورد مناسب اش استفاده کنید تا با this.Resources جور در بیاد.

در کد اول ، متد Begin در خط دوم ، وقتی شی this را بهش دادیم ، یعنی شیِ window جاری مون را انیمیشن میکنه؟ اگه آره ، چه پروپرتی ای از شیِ window مون را انیمیت میکنه؟
در حالت کلی this ئه حوزه رو مشخص میکنه، scope ئه.
اگر Storyboard.TargetName ها برای همه موارد داخل Storyboard مشخص باشه، این this ئه والد یا جد اون TargetName ها است، ولی اگر موردی در Storyboard باشه که برایش TargetName مشخص نکرده اید، اون مورد روی همین this اجرا میشه. مثلا وقتی MyTranslateTransform صریحا مشخص شده، اون this باید در حوزه ای باشه که MyTranslateTransform داخلش وجود داره، حالا مهم نیست که this پدرش باشه یا جد اش.
ولی اگر در توصیف انیمیشن اشاره ای به MyTranslateTransform نشده بود، روی همون this اجرا میشد.

همچنین بخش FillBehavior.Stop Doesn't Work as Expected را متوجه نشدم منظورش چیه؟
منظورم بخش FillBehavior="Stop" and HandoffBehavior with Multiple Animations نیست .
تشکر استاد
دارید تیتر کلی رو می خونید، FillBehavior.Stop Doesn't Work as Expected تیتر کلی ئه که میگه FillBehavior.Stop در شرایط متفاوتی ممکنه اونطور که انتظار دارید عمل نکنه، منظورش همینه. که نمی خواهید بدونید چه شرایطی است و به بخش های پایینی اش کاری ندارید. اگر دو بند زیرش رو نادیده بگیرید فقط همین دستگیر تون میشه که همچین شرایط هایی هم هست. که یکی از مثال هاش اون بخش FillBehavior="Stop" and HandoffBehavior with Multiple Animations ئه که میگید منظورتون اون نیست.
 

SajjadKhati

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

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

پس الان که در Storyboard مون ، اون TargetName مشخص هست ، این this ای که در آرگومان متد Storyboard.Begin داده شد ، مشخص کننده ی والد یا جد TargetName هست .
خوب والدش مشخص باشه یا نباشه ، چه فرقی میکنه؟

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

استاد ، میشه در یه پروپرتی ای که از نوع کالکشن هست و بصورت attributes (در xml منظورم هست) نمیشه ازش استفاده کرد و فقط بصورت content property میشه ازش استفاده کرد ، برای اون پروپرتی میشه از Resource استفاده کرد؟
مثلا پروپرتیِ Children در Grid که از نوع کالکشن هست و هم بصورت content property هست ، میشه این پروپرتی را جوری بنویسیم که از Resource ای که قبلا تعریف کردیم ، استفاده کنه؟ (حالا مثلا بصورت StaticResource) . اگه میشه ، چجوری میشه؟

به عبارتی دیگه ، در کد زیر :

کد:
<Window x:Class="WPF_Practice.Window2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPF_Practice"
        mc:Ignorable="d"
        Title="Window2" Height="450" Width="800">
 
 
    <Window.Resources>
        <Grid x:Key="overalControl">
         
        </Grid>
    </Window.Resources>
 
 
    <Grid Name="grdLevel_1">
        <Grid Name="grdLevel_2">
         
        </Grid>
    </Grid>
</Window>

میشه از Resource ای که تعریف کردیم (اون overalControl) ، در پروپرتیِ Children در کنترلِ grdLevel_2 یا grdLevel_1 استفاده کنیم؟ اگه آره ، کدش چجوری میشه؟

اگه نمیشه ، بهترین کنترلی که بشه بجای کنترل grdLevel_2 استفاده کرد ، جوری که ظاهری نداشته باشه و بشه اون کنترل overalControl را در اون استفاده کرد و قابلیت Resource شدن داشته باشه ، کنترل ContentControl هست؟ یا مناسب تر از این کنترل ، برای این کار هم وجود داره؟ اگه وجود داره ، کدوم کنترل هه؟ (پروپرتی Content را در کنترل ContentControl باید ResourceStaticResource کنم دیگه؟)

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

و اینکه استاد ، کلاس های ContentElement و FrameworkContentElement برای چی هستن؟
من با کلاس هایی که فرزند کلاس Visual هستن تا حالا کار کردم . با برادر و خواهرهای Visual ، مثل ContentElement (و کلا بقیه ی فرزندان DependencyObject) ، کار نکردم. بجز Visual و فرزندان Visual ، کنترل های بصری دیگه ای که فرزند DependencyObject باشن ، وجود داره؟
 
آخرین ویرایش:

the_king

مدیرکل انجمن
پس الان که در Storyboard مون ، اون TargetName مشخص هست ، این this ای که در آرگومان متد Storyboard.Begin داده شد ، مشخص کننده ی والد یا جد TargetName هست .
خوب والدش مشخص باشه یا نباشه ، چه فرقی میکنه؟
چه فرقی می کنه؟ فرضا در یک Storyboard مثل اونی که در Style ئه ComboBox هست، "Storyboard.TargetName="Border ئه، کدوم "Border"؟ میتونه ده تا ComboBox در پنجره باشه که یک المنت "Border" دارن. TargetName که منحصر بفرد نیست، ممکنه چند تا پنجره داشته باشید که هر کدوم یک Button1 داشته باشند. اینکه روی کدوم شون انیمیشن اجرا بشه فرقی نمی کنه؟

استاد ، میشه در یه پروپرتی ای که از نوع کالکشن هست و بصورت attributes (در xml منظورم هست) نمیشه ازش استفاده کرد و فقط بصورت content property میشه ازش استفاده کرد ، برای اون پروپرتی میشه از Resource استفاده کرد؟
مثلا پروپرتیِ Children در Grid که از نوع کالکشن هست و هم بصورت content property هست ، میشه این پروپرتی را جوری بنویسیم که از Resource ای که قبلا تعریف کردیم ، استفاده کنه؟ (حالا مثلا بصورت StaticResource) . اگه میشه ، چجوری میشه؟

به عبارتی دیگه ، در کد زیر :

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


    <Window.Resources>
        <Grid x:Key="overalControl">
       
        </Grid>
    </Window.Resources>


    <Grid Name="grdLevel_1">
        <Grid Name="grdLevel_2">
       
        </Grid>
    </Grid>
</Window>

میشه از Resource ای که تعریف کردیم (اون overalControl) ، در پروپرتیِ Children در کنترلِ grdLevel_2 یا grdLevel_1 استفاده کنیم؟ اگه آره ، کدش چجوری میشه؟
مورد جدید و ناشناخته ای براتون نداره.
کد:
    <Window.Resources>
        <Grid x:Key="overalControl" Background="Red">
        </Grid>
    </Window.Resources>
    <Grid Name="grdLevel_1">
        <Grid Name="grdLevel_2">
            <ContentPresenter Content="{StaticResource overalControl}"/>
        </Grid>
    </Grid>

و اینکه استاد ، کلاس های ContentElement و FrameworkContentElement برای چی هستن؟
چرا توضیحات شون رو در سایت مایکروسافت نمی خونید؟ زیربنای المنت های Content دار در Documents هستند.
من با کلاس هایی که فرزند کلاس Visual هستن تا حالا کار کردم . با برادر و خواهرهای Visual ، مثل ContentElement (و کلا بقیه ی فرزندان DependencyObject) ، کار نکردم. بجز Visual و فرزندان Visual ، کنترل های بصری دیگه ای که فرزند DependencyObject باشن ، وجود داره؟
بله.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
چه فرقی می کنه؟ فرضا در یک Storyboard مثل اونی که در Style ئه ComboBox هست، "Storyboard.TargetName="Border ئه، کدوم "Border"؟ میتونه ده تا ComboBox در پنجره باشه که یک المنت "Border" دارن. TargetName که منحصر بفرد نیست، ممکنه چند تا پنجره داشته باشید که هر کدوم یک Button1 داشته باشند. اینکه روی کدوم شون انیمیشن اجرا بشه فرقی نمی کنه؟

سلامی مجدد استاد . خیلی ممنون .
من بگم دقیقا متوجه ی منظورتون نشدم ، دعوام نمیکنین؟ :green:
مگه هر شی ای که بهش ، نام ای اختصاص میدیم (چه با پروپرتیِ Name یا با x:Name) ، نباید منحصر به فرد باشه؟
یعنی 2 تا نامِ شبیه هم را نمیشه به دو شی متفاوت اختصاص داد دیگه . درسته؟ (وگرنه xaml در wpf خطا میده) .
پس Storyboard.TargetName ای که برای هر شی ست میکنیم ، جدا از هم میشن دیگه .
از جواب بقیه ی قسمت ها هم ممنون .

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

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

Key-Frame Animations Overview - WPF

قضیه ی نمودار Key Frame Animation ، این طوری هست که در زیر توضیح میدم؟ :

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

کد:
            <Border Name="border6AnimKeyFrameWidth" Margin="10,360,0,0" Width="100" Height="100"  Background="#FF4D8B56" HorizontalAlignment="Left" VerticalAlignment="Top">
                <Border.Child>
                    <TextBlock Foreground="White" FontSize="18" IsHitTestVisible="False" Text="Click For KeyFrame Width Animation" TextWrapping="Wrap" />
                </Border.Child>

                <Border.Triggers>
                    <EventTrigger RoutedEvent="UIElement.MouseDown">
                        <EventTrigger.Actions>
                            <BeginStoryboard>
                                <BeginStoryboard.Storyboard>
                                    <Storyboard
                                                Storyboard.TargetName="border6AnimKeyFrameWidth"
                                                Storyboard.TargetProperty="Width"
                                                FillBehavior="Stop">
                                        <Storyboard.Children>
                                            <DoubleAnimationUsingKeyFrames Duration="0:0:10">
                                                <DoubleAnimationUsingKeyFrames.KeyFrames>
                                                    <LinearDoubleKeyFrame x:Name="firstKeyFrame" KeyTime="0:0:0" Value="100"/>
                                                    <SplineDoubleKeyFrame x:Name="secondKeyFrame" KeyTime="0:0:10" Value="500" KeySpline="0,1 1,0"/>
                                                </DoubleAnimationUsingKeyFrames.KeyFrames>
                                            </DoubleAnimationUsingKeyFrames>
                                        </Storyboard.Children>
                                    </Storyboard>
                                </BeginStoryboard.Storyboard>
                            </BeginStoryboard>
                        </EventTrigger.Actions>
                    </EventTrigger>
                </Border.Triggers>
            </Border>

اون شکل ، بصورت زیر میشه؟ :

3.jpg

اول اینکه هر وقت زمانی که در key frame ها مشخص کردیم ، به اون زمان برسه ، خودِ همون نوعِ key frame ای که مشخص کرده بودیم ، اجرا نمیشه . بلکه key frame ئه بعدی اش اجرا میشه . مثلا در کد بالا ، وقتی ثانیه ی 0 ام شروع شد ، اون کیفریم با نامِ firstKeyFrame که مشخص کرده بودیم ، اجرا نمیشه بلکه متد و روشِ کیفریمِ بعدیش که نامِ secondKeyFrame داره ، اجرا میشه .
بنابراین در هر نوع کیفریم ای ، برای لحظه ی ثانیه ی 0 ام ، چه کیفریم ای تعیین کنیم یا نکنیم ، روشِ کیفریمِ بعدی اجرا میشه (یعنی در کد بالا ، از لحظه ی 0 تا 10 ثانیه ، به روشِ secondKeyFrame پیش میره) .

بعد اینکه اون کیفریم (در اینجا ، secondKeyFrame) ، از مقدار زمانِ کیفریمِ قبلی (در مثال ، زمان 0) شروع میشه تا مقدارِ زمانی که در همین کیفریم خودش مشخص میشه (در مثال ، زمان 10 ثانیه) ختم میشه و همچنین از مقداری که برای اون پروپرتی در کیفریمِ قبلی مشخص کرده بودیم (Target Value در firstKeyFrame که همون 100 هست) شروع میشه تا مقداری که برای اون پروپرتی در کیفریمِ خودش مشخص کرده بودیم (Target Value در secondKeyFrame که همون 500 هست) ، ختم میشه .
و همچنین در نمودار ، محور پایین (محور X در ریاضی) ، همون مقدارِ Time ما میشه و محور بالایی (محور Y در ریاضی) ، همون مقدارِ Target Value (در اینجا پروپرتیِ Width هست) میشه .

بنابراین ، هر چقدر که زمان (همون محور X در بالا) ، جلو میره ، به همون نسبتی که در نمودار مشخص هست ، مقدار Width ما هم تغییر میکنه .
یعنی در لحظه ی 0 ، مقدار Width ئه ما ، 100 هست .
در ثانیه ی 1 ، مقدار Width ئه ما تقریبا 260 هست .
در ثانیه ی 2 ، مقدار Width ئه ما تقریبا 290 هست .
در ثانیه ی 3 تا 6 ، مقدار Width ئه ما تقریبا 300 هست (ثابت هست) .
در ثانیه ی 7 ، مقدار Width ئه ما تقریبا 310 هست .
در ثانیه ی 8 ، مقدار Width ئه ما تقریبا 320 هست .
در ثانیه ی 9 ، مقدار Width ئه ما تقریبا 345 هست .
در ثانیه ی 10 ، مقدار Width ئه ما تقریبا 500 هست .

اینها درستن؟

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

اما من قضیه ی Path Animation را متوجه نشدم .
در واقع ، نمودارش را متوجه نشدم چجوری از آب درمیاد؟

یعنی الان اگه بخوایم مثال زیر را بصورت نمودار رسم کنیم ، محور X ها چه چیزی میشه (مثلا در مثال بالا ، محور X ها Time شد) و محور Y ها هم چی میشه (مثلا در مثال بالا ، محور Y ها ، Target Value شد) ؟
بعد مقادیرِ این محورها از چه مقداری تا چه مقداری میشن؟ :

کد:
            <Border Name="border5AnimPathWidth" Margin="520,240,0,0" Width="100" Height="100"  Background="#FFF19A00" HorizontalAlignment="Left" VerticalAlignment="Top">
                <Border.Child>
                    <TextBlock Foreground="White" FontSize="18" IsHitTestVisible="False" Text="Click For Path KeyFrame Width Animation" TextWrapping="Wrap" />
                </Border.Child>

                <Border.Triggers>
                    <EventTrigger RoutedEvent="UIElement.MouseDown">
                        <EventTrigger.Actions>
                            <BeginStoryboard>
                                <BeginStoryboard.Storyboard>
                                    <Storyboard
                                                Storyboard.TargetName="border5AnimPathWidth"
                                                Storyboard.TargetProperty="Width"
                                                FillBehavior="Stop">
                                        <Storyboard.Children>
                                            <DoubleAnimationUsingPath Duration="0:0:5">
                                             
                                                <DoubleAnimationUsingPath.PathGeometry>
                                                    <PathGeometry>
                                                        <PathGeometry.Figures>
                                                            <PathFigure StartPoint="0,50" >
                                                                <PathFigure.Segments>
                                                                    <ArcSegment Point="400, 50" Size="1,10" SweepDirection="Clockwise"/>
                                                                </PathFigure.Segments>
                                                            </PathFigure>
                                                        </PathGeometry.Figures>
                                                    </PathGeometry>
                                                </DoubleAnimationUsingPath.PathGeometry>
                                                 
                                            </DoubleAnimationUsingPath>
                                        </Storyboard.Children>
                                    </Storyboard>
                                </BeginStoryboard.Storyboard>
                            </BeginStoryboard>
                        </EventTrigger.Actions>
                    </EventTrigger>
                </Border.Triggers>
            </Border>

من فکر کنم این بار (در قضیه ی Path Animation ها) بر عکس بشه ، یعنی محور Y ها ، Time مون بشه و مقدارِ Target Value مون هم همون محور X ها هست . درسته؟
اما مقدار شروع را دقیقا نمیدونم از کجا بیاد ولی زمان ، از 0 شروع و تا 5 (ثانیه) ختم بشه (یعنی حداکثرِ مقدار محور Y ها ، 5 هست) و مقدار Target Value مون هم از 0 شروع و تا X ئه Point ای که در ArcSegment تعیین کردیم ، یعنی تا مقدار 400 ختم بشه . درسته؟
مقادیر شروعش را یه کم گیج شدم از کجا اومد . کلا توی قضیه ی Path Animation ، دقیق نمیدونم کدوم محور برای چیه و مقادیر شروع و پایانش از کجا میاد؟
تشکر استاد . :rose:
 

the_king

مدیرکل انجمن
سلامی مجدد استاد . خیلی ممنون .
من بگم دقیقا متوجه ی منظورتون نشدم ، دعوام نمیکنین؟ :green:
مگه هر شی ای که بهش ، نام ای اختصاص میدیم (چه با پروپرتیِ Name یا با x:Name) ، نباید منحصر به فرد باشه؟
یعنی 2 تا نامِ شبیه هم را نمیشه به دو شی متفاوت اختصاص داد دیگه . درسته؟ (وگرنه xaml در wpf خطا میده) .
پس Storyboard.TargetName ای که برای هر شی ست میکنیم ، جدا از هم میشن دیگه .
دو تا مورد متفاوت رو دارید قاطی می کنید، شما در یک پنجره XAML تون دو تا Border (شیء) رو توصیف می کنید، نام هر کدوم شون داخل اون پنجره منحصر بفرد ئه، فرضا "Border1" و "Border2"
اما در دو تا Style متفاوت دو تا Border متفاوت رو توصیف می کنید که نام هر دوشون "Border" ئه. این "Border" منحصر بفرد هست، اما داخل همون Style اش. نه در کل پنجره XAML، نه برای Storyboard ئه.
شما به عنوان یک Resource یک Storyboard ای رو توصیف می کنید که داخلش یک "Storyboard.TargetName="Border ای داره. این TargetName روی کدوم اشیاء قابل اجرا است؟
هر جا شی ای به نام "Border" باشه با این TargetName جور در میاد.
ممکنه المنت هایی از انواع مختلف یک "Border" داشته باشند، این نام "Border" منحصر بفرد ئه؟ برای گستردگی جایی که این Storyboard قابل اجرا است که منحصر بفرد نیست.
شما چند تا المنت می توانید داشته باشید که در Style شون شیء ای با نام "Border" داشته باشند؟ چند تا Style می توانید داشته باشید که "Border" دارند؟ صد تا هم ممکنه باشه.
این Storyboard روی هر کدوم از اونها قابل اجرا است. "Border" شیء 1 با "Border" شی 2 اسامی یکسانی دارند، اما خودشون که یکسان نیستند.

اول اینکه هر وقت زمانی که در key frame ها مشخص کردیم ، به اون زمان برسه ، خودِ همون نوعِ key frame ای که مشخص کرده بودیم ، اجرا نمیشه . بلکه key frame ئه بعدی اش اجرا میشه . مثلا در کد بالا ، وقتی ثانیه ی 0 ام شروع شد ، اون کیفریم با نامِ firstKeyFrame که مشخص کرده بودیم ، اجرا نمیشه بلکه متد و روشِ کیفریمِ بعدیش که نامِ secondKeyFrame داره ، اجرا میشه .
بنابراین در هر نوع کیفریم ای ، برای لحظه ی ثانیه ی 0 ام ، چه کیفریم ای تعیین کنیم یا نکنیم ، روشِ کیفریمِ بعدی اجرا میشه (یعنی در کد بالا ، از لحظه ی 0 تا 10 ثانیه ، به روشِ secondKeyFrame پیش میره) .
خیر. همون اولی هم اجرا میشه. اما این KeyFrame های Linear و Spline پیوسته هستند، منقطع نیستند، شما خواسته اید که در ثانیه 0 طول به 100 برسه، خودش همون اول هم 100 بوده و در همون لحظه ابتدایی به 100 میرسه و تمام. طبعا شما تاثیرش رو نمی بینید چون از اول همون بوده.
شما مقداری اولی رو از "Value="100 به "Value="500 تغییر بدهید و ببینید با چه سرعتی میپره به 500. مجبوره، چون شما گفته اید در عرض 0 ثانیه باید به 500 برسی.

بعد اینکه اون کیفریم (در اینجا ، secondKeyFrame) ، از مقدار زمانِ کیفریمِ قبلی (در مثال ، زمان 0) شروع میشه تا مقدارِ زمانی که در همین کیفریم خودش مشخص میشه (در مثال ، زمان 10 ثانیه) ختم میشه و همچنین از مقداری که برای اون پروپرتی در کیفریمِ قبلی مشخص کرده بودیم (Target Value در firstKeyFrame که همون 100 هست) شروع میشه تا مقداری که برای اون پروپرتی در کیفریمِ خودش مشخص کرده بودیم (Target Value در secondKeyFrame که همون 500 هست) ، ختم میشه .
بله.

و همچنین در نمودار ، محور پایین (محور X در ریاضی) ، همون مقدارِ Time ما میشه و محور بالایی (محور Y در ریاضی) ، همون مقدارِ Target Value (در اینجا پروپرتیِ Width هست) میشه .
نه دقیقا، محور افقی به زمان مربوط ئه، اما مقدار Time نیست، محور عمودی هم به Width مربوط ئه، اما اون هم مقدار Width نیست. این منحنی فاکتور سرعت تغییرات Width ئه، نه خود Width.
اگر خود Time و خود Width بود همیشه از زمان 0 و مقدار Width ئه 0 شروع میشد، نه این منحنی همیشه از 0 و 0 شروع میشه و به 1 و 1 میرسه.
چیزی که تغییر میکنه فاکتور تغییرات اون مقدار Width ئه که میتونه کندتر یا سریعتر بشه.

بنابراین ، هر چقدر که زمان (همون محور X در بالا) ، جلو میره ، به همون نسبتی که در نمودار مشخص هست ، مقدار Width ما هم تغییر میکنه .
یعنی در لحظه ی 0 ، مقدار Width ئه ما ، 100 هست .
در ثانیه ی 1 ، مقدار Width ئه ما تقریبا 260 هست .
در ثانیه ی 2 ، مقدار Width ئه ما تقریبا 290 هست .
در ثانیه ی 3 تا 6 ، مقدار Width ئه ما تقریبا 300 هست (ثابت هست) .
در ثانیه ی 7 ، مقدار Width ئه ما تقریبا 310 هست .
در ثانیه ی 8 ، مقدار Width ئه ما تقریبا 320 هست .
در ثانیه ی 9 ، مقدار Width ئه ما تقریبا 345 هست .
در ثانیه ی 10 ، مقدار Width ئه ما تقریبا 500 هست .
اینها درستن؟
بله. اما در این مثال. ممکنه اول زیاد بشه و بعد کم بشه و بعد دوباره زیاد بشه و آخرش هم اون 500 نشه.
کد:
                                        <DoubleAnimationUsingKeyFrames Duration="0:0:10">
                                            <DoubleAnimationUsingKeyFrames.KeyFrames>
                                                <LinearDoubleKeyFrame x:Name="firstKeyFrame" KeyTime="0:0:0" Value="100"/>
                                                <SplineDoubleKeyFrame x:Name="secondKeyFrame" KeyTime="0:0:10" Value="500" KeySpline="0,2 1,-2"/>
                                            </DoubleAnimationUsingKeyFrames.KeyFrames>
                                        </DoubleAnimationUsingKeyFrames>

من فکر کنم این بار (در قضیه ی Path Animation ها) بر عکس بشه ، یعنی محور Y ها ، Time مون بشه و مقدارِ Target Value مون هم همون محور X ها هست . درسته؟
اما مقدار شروع را دقیقا نمیدونم از کجا بیاد ولی زمان ، از 0 شروع و تا 5 (ثانیه) ختم بشه (یعنی حداکثرِ مقدار محور Y ها ، 5 هست) و مقدار Target Value مون هم از 0 شروع و تا X ئه Point ای که در ArcSegment تعیین کردیم ، یعنی تا مقدار 400 ختم بشه . درسته؟
مقادیر شروعش را یه کم گیج شدم از کجا اومد . کلا توی قضیه ی Path Animation ، دقیق نمیدونم کدوم محور برای چیه و مقادیر شروع و پایانش از کجا میاد؟
برعکس نیست، X ئه مقدار Target Value تون بوده ولی Y ئه Time نیست.
چطور منحنی SplineDoubleKeyFrame تعیین می کرد که مقدار Width چطور تغییر کنه. اینجا هم یک منحنی دلخواه که دیگه الزاما Bezier نیست مشخص می کنید تا طبق اون منحنی پیش بره و مقدار Width بر اساسش تعیین بشه.
کد:
                                    <DoubleAnimationUsingPath Duration="0:0:10" Source="Y">
                                        <DoubleAnimationUsingPath.PathGeometry>
                                            <PathGeometry>
                                                <PathFigure StartPoint="0,100">
                                                    <LineSegment Point="0.5,500"/>
                                                    <LineSegment Point="1.0,100"/>
                                                </PathFigure>
                                            </PathGeometry>
                                        </DoubleAnimationUsingPath.PathGeometry>
                                    </DoubleAnimationUsingPath>
Source پیشفرض X ئه اما Y ئه Time نیست، بخشی از طول Path ئه که پیمایش شده Time ئه. لزومی نداشت که از مقادیر 0.0 الی 1.0 استفاده کنم.
کد:
                                    <DoubleAnimationUsingPath Duration="0:0:10" Source="Y">
                                        <DoubleAnimationUsingPath.PathGeometry>
                                            <PathGeometry>
                                                <PathFigure StartPoint="0,100">
                                                    <LineSegment Point="1000,500"/>
                                                    <LineSegment Point="0,100"/>
                                                </PathFigure>
                                            </PathGeometry>
                                        </DoubleAnimationUsingPath.PathGeometry>
                                    </DoubleAnimationUsingPath>
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
برعکس نیست، X ئه مقدار Target Value تون بوده ولی Y ئه Time نیست.
چطور منحنی SplineDoubleKeyFrame تعیین می کرد که مقدار Width چطور تغییر کنه. اینجا هم یک منحنی دلخواه که دیگه الزاما Bezier نیست مشخص می کنید تا طبق اون منحنی پیش بره و مقدار Width بر اساسش تعیین بشه.
کد:
                                    <DoubleAnimationUsingPath Duration="0:0:10" Source="Y">
                                        <DoubleAnimationUsingPath.PathGeometry>
                                            <PathGeometry>
                                                <PathFigure StartPoint="0,100">
                                                    <LineSegment Point="0.5,500"/>
                                                    <LineSegment Point="1.0,100"/>
                                                </PathFigure>
                                            </PathGeometry>
                                        </DoubleAnimationUsingPath.PathGeometry>
                                    </DoubleAnimationUsingPath>
Source پیشفرض X ئه اما Y ئه Time نیست، بخشی از طول Path ئه که پیمایش شده Time ئه. لزومی نداشت که از مقادیر 0.0 الی 1.0 استفاده کنم.
کد:
                                    <DoubleAnimationUsingPath Duration="0:0:10" Source="Y">
                                        <DoubleAnimationUsingPath.PathGeometry>
                                            <PathGeometry>
                                                <PathFigure StartPoint="0,100">
                                                    <LineSegment Point="1000,500"/>
                                                    <LineSegment Point="0,100"/>
                                                </PathFigure>
                                            </PathGeometry>
                                        </DoubleAnimationUsingPath.PathGeometry>
                                    </DoubleAnimationUsingPath>

خیلی ممنون استاد (همچنین تشکر از بابت بقیه ی قسمت های جواب هایی که دادین) .
این تیکه را من باز دقیقا متوجه نشدم .
البته متوجه شدم که وقتی پروپرتیِ Source ئه DoubleAnimationUsingPath را X قرار میدیم ، در اشیاء ئه Segment هامون که نقطه ای را میدیم ، فقط نقطه ی مربوط به X در نظر گرفته میشه و نقطه ی مربوط به Y در نظر گرفته نمیشه . و همچنین وقتی اون پروپرتی را روی مقدار Y قرار میدیم ، فقط نقطه ی مربوط به Y در نظر گرفته میشه و نقطه ی مربوط به X در نظر گرفته نمیشه .

اما باز خوب درک نکردم چون هنوز کاملا برام نمودار با مقادیرهاش مشخص نیست . یعنی الان شما گفتین که در نمودارِ مربوط به DoubleAnimationUsingPath ، محور X هاش مربوط به Target Value هست . اما مقادیرِ شروع و پایانش از کجا میاد؟ (آیا از کمترین مقدار و بیشترین مقداری که تعیین کردیم (با توجه به مقدار Source) ، از اینجا میاد؟)
اما نمودارِ مربوط به Y هاش چی میشه؟ من الان دقیقا متوجه نشدم که نمودار Y هاش ، زمان هست یا نیست . چون شیِ انیمیشن ، شیِ TimeLine هست ، پس با وجودِ زمان هست که معنا داره . بدون زمان ، اصلا انیمیشن معنا نداره .
زمان هم چون فقط یه دونه میشه بهش داد و بصورت کیفریم نیست ، از لحظه ی 0 شروع میشه تا زمانی که ما در Duration مشخص کرده بودیم؟

کلا درباره ی اینکه در قضیه ی Path Animation ، محور X ها که برای Target Value شد ، حالا از چه مقداری شروع تا چه مقداری ختم میشه و مخصوصا اینکه این مقادیر دقیقا از کجا اومدن و همچنین محور Y ها دقیقا برای چیه و از چه مقداری شروع تا چه مقداری ختم میشه و مخصوصا اینکه این مقادیر دقیقا از کجا اومدن را بیشتر توضیح میدین؟ (تا من بتونم نموداری رسم کنم تا بهتر متوجه بشم . بدون نمودار ، متوجه نمیشم) .

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

بعد اینکه استاد اگه بخوایم OpacityMask ئه یه کنترلی را انیمیشن کنیم ، باید از ObjectAnimationUsingKeyFrames استفاده کنیم دیگه؟
پروپرتیِ KeyFrames ئه ObjectAnimationUsingKeyFrames ، از نوع ObjectKeyFrame هست ، این کلاسِ ObjectKeyFrame ، ابسترکت هست . هر چند پیاده سازیِ DiscreteObjectKeyFrame (که از ObjectKeyFrame ارث بری میکنه) انجام شد ، ولی کلاسِ DiscreteObjectKeyFrame ، همونطور که مشخص هه ، از نوع Discrete هست . یعنی لحظه ی آخر ، یهو مقدار پروپرتی را تغییر میده . من میخوام بصورت خطی (Linear) تغییر بده .

برای تغییر مقدار پروپرتیِ OpacityMask بصورت خطی ، باید کلاس سفارشی بنویسم که از ObjectKeyFrame ارث بری کنه و متد ObjectKeyFrame.InterpolateValueCore را پیاده سازی کنه دیگه . درسته؟
در پارامتر اول این متد (baseValue) ، شیِ Object ای هست که میخوایم تغییرات روش انجام بدیم و در پارامتر دومش (keyFrameProgress) ، عددی بین 0 تا 1 که مشخص میکنه بین دو کی فریم ، چند درصد از زمان گذشت . درسته؟ حالا ما طبق این دو اطلاعات ، باید خروجیِ شی مون را به نسبتی که زمان طی شد ، تغییر بدیم؟ درسته؟

برای این کلاس مون (که از کلاس ObjectKeyFrame ارث بری میکرد) و کلاس قبلی اش که Freezable بود و اون هم abstract بود و عضو Freezable.CreateInstanceCore Method اش باید در کلاس مون پیاده سازی بشه ، اگه از خاصیت Freezable ئه کلاس مون استفاده نکنیم ، میتونیم بدنه ی این متد در کلاس مون را خالی بذاریم و مقدار این متد را null یا یه شی خالی برگردونیم؟
 

the_king

مدیرکل انجمن
خیلی ممنون استاد (همچنین تشکر از بابت بقیه ی قسمت های جواب هایی که دادین) .
این تیکه را من باز دقیقا متوجه نشدم .
البته متوجه شدم که وقتی پروپرتیِ Source ئه DoubleAnimationUsingPath را X قرار میدیم ، در اشیاء ئه Segment هامون که نقطه ای را میدیم ، فقط نقطه ی مربوط به X در نظر گرفته میشه و نقطه ی مربوط به Y در نظر گرفته نمیشه . و همچنین وقتی اون پروپرتی را روی مقدار Y قرار میدیم ، فقط نقطه ی مربوط به Y در نظر گرفته میشه و نقطه ی مربوط به X در نظر گرفته نمیشه .

اما باز خوب درک نکردم چون هنوز کاملا برام نمودار با مقادیرهاش مشخص نیست . یعنی الان شما گفتین که در نمودارِ مربوط به DoubleAnimationUsingPath ، محور X هاش مربوط به Target Value هست . اما مقادیرِ شروع و پایانش از کجا میاد؟ (آیا از کمترین مقدار و بیشترین مقداری که تعیین کردیم (با توجه به مقدار Source) ، از اینجا میاد؟)
از نقطه شروع تا پایان Path دیگه. شما Path رو از یک جایی شروع به توصیف می کنید، اون نقطه شروع ئه، جایی هم که توصیف تموم میشه پایان Path ئه. دقت کنید که فاصله خطی بین نقطه شروع و پایان یا فاصله خطی از نقطه شروع برای زمان ملاک نیست، طول مسیر پیموده شده ملاک ئه. مثلا ممکنه بین نقطه شروع و پایان اگه یک خط مستقیم رسم کنید خیلی فاصله کمی باشه، اما مسیر خیلی طولانی و پیچ در پیچ باشه. هر چقدر که از اون مسیر طولانی پیموده بشه به همون نسبت زمان جلو میره.

اما نمودارِ مربوط به Y هاش چی میشه؟ من الان دقیقا متوجه نشدم که نمودار Y هاش ، زمان هست یا نیست . چون شیِ انیمیشن ، شیِ TimeLine هست ، پس با وجودِ زمان هست که معنا داره . بدون زمان ، اصلا انیمیشن معنا نداره .
زمان هم چون فقط یه دونه میشه بهش داد و بصورت کیفریم نیست ، از لحظه ی 0 شروع میشه تا زمانی که ما در Duration مشخص کرده بودیم؟
صریحا گفتم که Y ئه Time نیست، چطوری هنوز شک دارید که زمان هست یا نیست؟ زمان نه با X محاسبه میشه و نه با Y. ترکیب اینها یک موقعیت رو مسیر ئه که اون موقعیت مهم ئه.
زمان نسبت به بخشی از مسیر که پیموده شده محاسبه میشه. مثلا اگه مسیر یک دایره باشه، طول مسیر، برابر محیط دایره است، روی هر نقطه از اون دایره که باشیم یک X و Y متفاوت داره، اگر روی محیط دایره حرکت کنید هم X و هم Y هم صعودی میشن و هم نزولی، هم در بخشی از مسیر کم میشن و هم در بخش دیگری زیاد میشن، اما زمان ربطی به این کم و زیاد شدن X یا Y نداره. بخشی از این مسیر دایره ای طی شده و بخشی اش باقی مونده.
اون بخشی که طی شده تقسیم بر کل اش میشه و در Duration ضرب میشه و زمان سپری شده بدست میاد.

بعد اینکه استاد اگه بخوایم OpacityMask ئه یه کنترلی را انیمیشن کنیم ، باید از ObjectAnimationUsingKeyFrames استفاده کنیم دیگه؟
سردر نمیارم که انیمیشن شدن یک OpacityMask یعنی چی. کاری ندارم که با کمک چه المنت ای میخواهید زمان بندی اش رو مشخص کنید، اما چطوری میخواهید به OpacityMask انیمیشن بدهید؟

برای تغییر مقدار پروپرتیِ OpacityMask بصورت خطی ، باید کلاس سفارشی بنویسم که از ObjectKeyFrame ارث بری کنه و متد ObjectKeyFrame.InterpolateValueCore را پیاده سازی کنه دیگه . درسته؟
خطی یعنی فرضا عدد ئه بین 0 الی 100 بصورت پیوسته و برحسب زمان افزایش پیدا کنه. خطی بودن برای یک OpacityMask چه معنی ای داره؟ مثلا OpacityMask تصویر یک مثلث ئه، این مثلث که بصورت خطی نمیشه تصویر یک مربع.
 

SajjadKhati

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


صریحا گفتم که Y ئه Time نیست، چطوری هنوز شک دارید که زمان هست یا نیست؟ زمان نه با X محاسبه میشه و نه با Y. ترکیب اینها یک موقعیت رو مسیر ئه که اون موقعیت مهم ئه.
زمان نسبت به بخشی از مسیر که پیموده شده محاسبه میشه. مثلا اگه مسیر یک دایره باشه، طول مسیر، برابر محیط دایره است، روی هر نقطه از اون دایره که باشیم یک X و Y متفاوت داره، اگر روی محیط دایره حرکت کنید هم X و هم Y هم صعودی میشن و هم نزولی، هم در بخشی از مسیر کم میشن و هم در بخش دیگری زیاد میشن، اما زمان ربطی به این کم و زیاد شدن X یا Y نداره. بخشی از این مسیر دایره ای طی شده و بخشی اش باقی مونده.
اون بخشی که طی شده تقسیم بر کل اش میشه و در Duration ضرب میشه و زمان سپری شده بدست میاد.

خیلی ممنون استاد .
الان منظورتون اینه که جایی که اون شکل (توصیفی که برای Path برای Animation داشته بودیم) ، شروع میشه (نقطه ی شروع) ، به عنوان لحظه ی 0 ام که همون 0 درصد از زمانِ سپری شده هست ، در نظر گرفته میشه و جایی که اون شکل تمام میشه ، به عنوان لحظه ی آخر که همون 100 درصد از زمان سپری شده هست ، در نظر گرفته میشه؟
هر جایی هم که بین این شکل باشه ، بسته به اینکه در کدوم نقطه باشه و چند درصد تا اتمام کل شکل مونده باشه ، به همون نسبت ، اون میزان از درصد از زمان ، سپری شده؟
حالا باز بیشتر فکر کنم روش .

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

خطی یعنی فرضا عدد ئه بین 0 الی 100 بصورت پیوسته و برحسب زمان افزایش پیدا کنه. خطی بودن برای یک OpacityMask چه معنی ای داره؟ مثلا OpacityMask تصویر یک مثلث ئه، این مثلث که بصورت خطی نمیشه تصویر یک مربع.

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

UIElement.OpacityMask هم که از نوع dependency property هست و هم کلاسش (UIElement) جزء کلاس هایی هست که IAnimatable را پیاده سازی کرد . پس ظاهرا باید بشه این پروپرتی را براش کلاسی بنویسیم تا قابلیت انیمیشن براش در نظر بگیریم دیگه؟ این طور نیست؟
کلا این قابلیت ماسک افترافکت (در ویدئو) را نمیشه در wpf هم انجام داد؟
تشکر
 

پیوست ها

  • 1.rar
    8.9 کیلوبایت · بازدیدها: 4

the_king

مدیرکل انجمن
خیلی ممنون استاد .
الان منظورتون اینه که جایی که اون شکل (توصیفی که برای Path برای Animation داشته بودیم) ، شروع میشه (نقطه ی شروع) ، به عنوان لحظه ی 0 ام که همون 0 درصد از زمانِ سپری شده هست ، در نظر گرفته میشه و جایی که اون شکل تمام میشه ، به عنوان لحظه ی آخر که همون 100 درصد از زمان سپری شده هست ، در نظر گرفته میشه؟
هر جایی هم که بین این شکل باشه ، بسته به اینکه در کدوم نقطه باشه و چند درصد تا اتمام کل شکل مونده باشه ، به همون نسبت ، اون میزان از درصد از زمان ، سپری شده؟
حالا باز بیشتر فکر کنم روش .
بله.

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

UIElement.OpacityMask هم که از نوع dependency property هست و هم کلاسش (UIElement) جزء کلاس هایی هست که IAnimatable را پیاده سازی کرد . پس ظاهرا باید بشه این پروپرتی را براش کلاسی بنویسیم تا قابلیت انیمیشن براش در نظر بگیریم دیگه؟ این طور نیست؟
کلا این قابلیت ماسک افترافکت (در ویدئو) را نمیشه در wpf هم انجام داد؟
تشکر
ارتباط بین افترافکت و wpf رو متوجه نمیشم که دارید مقایسه می کنید که فلان کار که در افترافکت میشه کرد رو میشه در wpf انجام داد یا نه.
WPF نرم افزار طراحی جلوه های ویژه و ویدئویی نیست، یک پلتفرم گرافیکی واسط کاربری است. دنبال یک جایگزین برای After Effect هستید؟
تغییر شکل تدریجی یک شکل به شکل دیگری Morphing ئه، بدون کتابخانه و پلاگین و کد آماده انجامش کار راحتی نیست، در هر صورت می توانید در مورد Morphing SVG و Morphing WPF جستجو کنید.
 

SajjadKhati

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


ارتباط بین افترافکت و wpf رو متوجه نمیشم که دارید مقایسه می کنید که فلان کار که در افترافکت میشه کرد رو میشه در wpf انجام داد یا نه.
WPF نرم افزار طراحی جلوه های ویژه و ویدئویی نیست، یک پلتفرم گرافیکی واسط کاربری است. دنبال یک جایگزین برای After Effect هستید؟
تغییر شکل تدریجی یک شکل به شکل دیگری Morphing ئه، بدون کتابخانه و پلاگین و کد آماده انجامش کار راحتی نیست، در هر صورت می توانید در مورد Morphing SVG و Morphing WPF جستجو کنید.

ممنون استاد .
اما یه جواب سئوالم را نگرفتم .
UIElement.OpacityMask که از نوع dependency property هست و هم کلاسش (UIElement) جزء کلاس هایی هست که IAnimatable را پیاده سازی کرد . پس ظاهرا باید بشه این پروپرتی را براش کلاسی بنویسیم تا قابلیت انیمیشن براش در نظر بگیریم دیگه؟ این طور نیست؟

یعنی خودمون نمیتونیم از کلاسِ ObjectKeyFrame ارث بری کنیم و متد ObjectKeyFrame.InterpolateValueCore اش را پیاده سازی کنیم تا به هدف مون (که انیمیت Opacity Mask هست) ، برسیم؟
پارامتر دوم متد InterpolateValueCore هم انگار درصدِ سپری شدن زمان را میده که میتونیم مثلا بگیم در فلان درصد ، این جور شکل را برگردون (برای رسم کردن) (مثلا x و y از فلان نقاط را ، فلان قدر تغییر بده) و در فلان درصد ، فلان شکل دیگه را (با تغییر x و y در نقاط اون شکل) .
این طور که گفتم ، شدنی هست؟
 

the_king

مدیرکل انجمن
ممنون استاد .
اما یه جواب سئوالم را نگرفتم .
UIElement.OpacityMask که از نوع dependency property هست و هم کلاسش (UIElement) جزء کلاس هایی هست که IAnimatable را پیاده سازی کرد . پس ظاهرا باید بشه این پروپرتی را براش کلاسی بنویسیم تا قابلیت انیمیشن براش در نظر بگیریم دیگه؟ این طور نیست؟
صورت مساله رو دور نزنید، مساله این نیست که چطور به OpacityMask مقدار بدهید، مساله اینه که چطور یک انیمیشن خطی بین دو Brush ای ایجاد کنید که به اون OpacityMask میتونه داده بشه.
اینکه در یک فریم به OpacityMask یک Brush رو بدهید که موضوع سوال شما نبود، موضوع اون انیمیشن خطی است که در پست 229 گفتید "میخوام خطی باشه".
فرض کنید که Brush نباشه و string باشه. صورت سوال ساده تر میشه. یک "A" رو در ثانیه 0 دادید و یک "B" رو در ثانیه 10 و میخواهید مقدار "A" بصورت تدریجی و با انیمیشن خطی تبدیل بشه به "B".
مساله اینجا نیست که چطور "A" و "B" در مشخصه قرار بگیرند، مشکل اینه که چطور string ئه باید بصورت تدریجی از "A" تبدیل بشه به "B". مقادیر تدریجی بین شون چیه و چطور بصورت خطی ایجاد بشه.
مساله این تغییر تدریجی Brush ئه، نه اینکه چطور "A" رو باید در مشخصه فلان قرار بدهیم. مساله که این نبود که چطور یک Brush رو باید در مشخصه OpacityMask قرار داد.

یعنی خودمون نمیتونیم از کلاسِ ObjectKeyFrame ارث بری کنیم و متد ObjectKeyFrame.InterpolateValueCore اش را پیاده سازی کنیم تا به هدف مون (که انیمیت Opacity Mask هست) ، برسیم؟
پارامتر دوم متد InterpolateValueCore هم انگار درصدِ سپری شدن زمان را میده که میتونیم مثلا بگیم در فلان درصد ، این جور شکل را برگردون (برای رسم کردن) (مثلا x و y از فلان نقاط را ، فلان قدر تغییر بده) و در فلان درصد ، فلان شکل دیگه را (با تغییر x و y در نقاط اون شکل) .
این طور که گفتم ، شدنی هست؟
جواب این سوال تون رو که در آخر پست قبلی داده بودم، بدون کتابخانه و پلاگین و کد آماده انجامش کار راحتی نیست.
 

SajjadKhati

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

Alignment, Margins, and Padding Overview - WPF

اولین شکلی که در این صفحه هست و رسم کرد را ببینید :

layout-margins-padding-alignment-graphic1.png


من ، همون کدها را نوشتم :

کد:
                <Border Background="LightBlue" BorderBrush="Black" Padding="15" BorderThickness="2" Width="500" Height="300" Margin="600, 320, 0, 0" HorizontalAlignment="Left" VerticalAlignment="Top">
                    <StackPanel Background="White" HorizontalAlignment="Center" VerticalAlignment="Top">
                        <TextBlock Margin="5,0,5,0" FontSize="18" HorizontalAlignment="Center" Text="Alignment, Margin and Padding Sample"/>
                        <Button HorizontalAlignment="Left" Margin="20" Content="Button 1"/>
                        <Button HorizontalAlignment="Right" Margin="10" Content="Button 2"/>
                        <Button HorizontalAlignment="Stretch" Margin="0" Content="Button 3"/>
                    </StackPanel>
                </Border>

اما ترازبندی و چیدمان من یه جور دیگه شد . چرا؟ :

10.JPG

Padding برای Border من و اون را با هم مقایسه کنید . واسه ی من ، 3 طرفِ چپ و راست و پایینش خیلی فاصله دارن . چرا؟ برای من در این 3 طرف ، فاصله شون 15 پیکسل (که برای padding مشخص کرده بودم) نیست اما برای اون هست . چرا؟


بعد اینکه الان وقتی HorizontalAlignment ئه Button1 را روی Left قرار میدیم و Margin اش را روی 20 قرار میدیم ، چرا Button1 ، مثل Button3 ، (تا مقدار HorizontalAlignment را روی Stretch قرار ندادیم) ، کشیده نمیشه (تا فقط 20 پیکسل از هر سمت ، از جمله از سمت راست ، با کناره های خونه ی مربوط به اون Stack ای که داخلش هست ، فاصله داشته باشه) ؟
چون میگم Width و Height ئه Button1 را که مشخص نکردیم (یعنی ، محدودیتی برای پهنا و ارتفاع اش مشخص نکردیم) . از اون طرف هم گفتیم بصورت افقی ، از سمت چپ خودش را تراز کنه (درباره ی سمت راست اش ، محدودیتی نذاشتیم جز اینکه فقط 20 پیکسل از سمت راستش فاصله داشته باشه) . پس چرا وقتی این 3 گزینه را برای Button1 که براش محدودیتی در نظر نگرفتیم ، Button1 را مثل Button3 ، کِش نمیاره (مگر اینکه فقط 20 پیکسل از سمت راست ، فاصله داشته باشه) ؟


بعد اینکه چرا وقتی دو مقدارِ اول را به Margin میدیم ، با وقتی که کامل ، هر 4 تا مقدارش را میدیم در صورتی که Width و Height را را هم مشخص کنیم ، گاها تراز بندی شون با هم فرق میکنه و گاها هم فرقی نمیکنه؟
تشکر
 

the_king

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

Alignment, Margins, and Padding Overview - WPF

اولین شکلی که در این صفحه هست و رسم کرد را ببینید :

layout-margins-padding-alignment-graphic1.png


من ، همون کدها را نوشتم :

کد:
                <Border Background="LightBlue" BorderBrush="Black" Padding="15" BorderThickness="2" Width="500" Height="300" Margin="600, 320, 0, 0" HorizontalAlignment="Left" VerticalAlignment="Top">
                    <StackPanel Background="White" HorizontalAlignment="Center" VerticalAlignment="Top">
                        <TextBlock Margin="5,0,5,0" FontSize="18" HorizontalAlignment="Center" Text="Alignment, Margin and Padding Sample"/>
                        <Button HorizontalAlignment="Left" Margin="20" Content="Button 1"/>
                        <Button HorizontalAlignment="Right" Margin="10" Content="Button 2"/>
                        <Button HorizontalAlignment="Stretch" Margin="0" Content="Button 3"/>
                    </StackPanel>
                </Border>

اما ترازبندی و چیدمان من یه جور دیگه شد . چرا؟ :
ایرادی از اجزاء داخل Border نیست، StackPanel و محتویاتش مشکلی ندارند، اما مساله اینجا است که شما "Width="500" Height="300 رو برای Border بر چه اساسی حساب کردین؟
شما Border ای که در یک ابعاد خودکاری قرار داشته که با محتویاتش جور بوده بزور تغییر ابعاد دادید، خوب طبعا فاصله اجزاء داخلش از کادر متفاوت میشه.
StackPanel داخلش یک ابعاد خودکاری داره بر اساس محتویات داخلش، و قراره Center قرار بگیره، نه اینکه Stretch کنه.
یعنی حتی اگه برای Border شما 500 بزرگتر از اون ابعاد خودکار اش باشه، طول StackPanel ئه بیشتر نمیشه، صرفا در وسط Border قرار میگیره، پس فاصله از گوشه ها بیشتر میشه.
این چیزی ئه که شما خواستید که باشه. شما به StackPanel نگفته اید که اگر Border بزرگتر شد تو هم Stretch کن.

در نظر بگیرید که Margin و HorizontalAlignment و VerticalAlignment و Width و Height وقتی معنا پیدا می کنن که با هم جور در بیان.
 

SajjadKhati

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

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

در کد زیر :

کد:
                <Grid Name="myGrid" Background="LightSteelBlue" Height="150" ShowGridLines="True">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="250"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>
                    <TextBlock Name="txt1" Margin="5" FontSize="18" FontFamily="Verdana" Grid.Column="0" Grid.Row="0">Hello World!</TextBlock>
                    <Button  Grid.Column="0" Grid.Row="1">Show Bounding Box</Button>
                    <TextBlock Name="txt2" Grid.Column="1" Grid.Row="2"/>
                </Grid>

که برگرفته از کد اول در لینک زیر (با کمی تغییرات) هست :

Layout - WPF

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

10.JPG

چرا در این دکمه ای که قرار داره و Alignment هاش را مشخص نکردیم (و چون Width و Height هم بهش ندادیم) ، پس Alignment هاش بصورت پیش فرض روی Stretch هست ، پس این دکمه چرا فقط بخشی از خونه ی دوم از grid مون را گرفته؟ چرا بخش زیادی از سمت راست اش در اون خونه از grid که دکمه مون توشه ، خالی هه و دکمه مون اون بخش ها را نمیتونه بگیره؟
و اگه بخوایم دکمه مون کل اون خونه از grid که توش هست را احاطه کنه ، باید چی کار کنیم؟
تشکر
 

the_king

مدیرکل انجمن
بعد اینکه الان وقتی HorizontalAlignment ئه Button1 را روی Left قرار میدیم و Margin اش را روی 20 قرار میدیم ، چرا Button1 ، مثل Button3 ، (تا مقدار HorizontalAlignment را روی Stretch قرار ندادیم) ، کشیده نمیشه (تا فقط 20 پیکسل از هر سمت ، از جمله از سمت راست ، با کناره های خونه ی مربوط به اون Stack ای که داخلش هست ، فاصله داشته باشه) ؟
وقتی HorizontalAlignment رو روی Left قرار می دهید یعنی نمی خواهید Stretch صورت بگیره، اگر می خواستید کشیده بشه روی Stretch قرار می دادید.
Margin یعنی حداقل فلان فاصله رو از اجزاء دیگه حفظ کنه، نه اینکه اونقدر کشیده بشه که فاصله بیشتری باقی نمونه.

چون میگم Width و Height ئه Button1 را که مشخص نکردیم (یعنی ، محدودیتی برای پهنا و ارتفاع اش مشخص نکردیم) . از اون طرف هم گفتیم بصورت افقی ، از سمت چپ خودش را تراز کنه (درباره ی سمت راست اش ، محدودیتی نذاشتیم جز اینکه فقط 20 پیکسل از سمت راستش فاصله داشته باشه) . پس چرا وقتی این 3 گزینه را برای Button1 که براش محدودیتی در نظر نگرفتیم ، Button1 را مثل Button3 ، کِش نمیاره (مگر اینکه فقط 20 پیکسل از سمت راست ، فاصله داشته باشه) ؟
نگفتید که از سمت راست 20 پیکسل فاصله داشته باشه، گفتید از سمت راست با اجزاء دیگه فاصله حداقلی 20 رو حفظ کنه. Stretch کردن و نکردن ربطی به Margin نداره. به HorizontalAlignment مربوط بود که گفتید نکنه.

بعد اینکه چرا وقتی دو مقدارِ اول را به Margin میدیم ، با وقتی که کامل ، هر 4 تا مقدارش را میدیم در صورتی که Width و Height را را هم مشخص کنیم ، گاها تراز بندی شون با هم فرق میکنه و گاها هم فرقی نمیکنه؟
تشکر
در جایی که فاصله در سمتی بصورت عادی از حداقل بیشتر شده Margin ئه برای اون سمت بود و نبودش تاثیری نداره.
 

the_king

مدیرکل انجمن
خیلی ممنون استاد .
اون 2 تا سئوال بعدی در پست قبلی ام را هم بی زحمت جواب میدین؟ (جواب قبلی تون ، مال سئوال اولی ام بود) .

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

در کد زیر :

کد:
                <Grid Name="myGrid" Background="LightSteelBlue" Height="150" ShowGridLines="True">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="250"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>
                    <TextBlock Name="txt1" Margin="5" FontSize="18" FontFamily="Verdana" Grid.Column="0" Grid.Row="0">Hello World!</TextBlock>
                    <Button  Grid.Column="0" Grid.Row="1">Show Bounding Box</Button>
                    <TextBlock Name="txt2" Grid.Column="1" Grid.Row="2"/>
                </Grid>

که برگرفته از کد اول در لینک زیر (با کمی تغییرات) هست :

Layout - WPF

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

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

چرا در این دکمه ای که قرار داره و Alignment هاش را مشخص نکردیم (و چون Width و Height هم بهش ندادیم) ، پس Alignment هاش بصورت پیش فرض روی Stretch هست ، پس این دکمه چرا فقط بخشی از خونه ی دوم از grid مون را گرفته؟ چرا بخش زیادی از سمت راست اش در اون خونه از grid که دکمه مون توشه ، خالی هه و دکمه مون اون بخش ها را نمیتونه بگیره؟
و اگه بخوایم دکمه مون کل اون خونه از grid که توش هست را احاطه کنه ، باید چی کار کنیم؟
تشکر
منظورتون از بخشی از خونه دوم چیه؟ به نظرتون Width دکمه از 250 کمتر شده؟ کمتر نیست، کل خانه "Grid.Column="0" Grid.Row="1 رو پوشش داده.
 

SajjadKhati

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

خیلی ممنون استاد .
استاد ، من هنوز قشنگ این مسئله برام جا نیافتاد .
که چطور میشه مثلا وقتی برای کنترلی ، دو مقدارِ اولِ Margin را مشخص میکنیم (مثلا مینویسیم Marging = "20,50") با زمانی که 4 مقدار را بصورت کامل مشخص میکنیم (مثلا مینویسیم Margin = "20, 30, 0, 0") نتیجه شون و چیدمان اون کنترل ، با حالت قبلی فرق میکنه . چرا؟
نمیدونم چه تغییری میکنه فقط میدونم گاها ، فرق دارن با هم . اول اینکه میگید ، دقیقا چیدمان این دو نوع کد ، چه فرقی با هم میکنن؟
دوم اینکه از لحاظ برنامه نویسی هم بخوایم پیش بریم ، چون در کد اولی (یعنی زمانی که فقط 2 مقدار از Marging را مشخص کردیم) و پروپرتی های Right و Bottom را مشخص نکردیم ، چون این پروپرتی ها از نوع double که value type هست ، پس وقتی ما مشخص نکنیم ، باید بصورت پیش فرض مقدارش را 0 بگیره دیگه . اگه بصورت پیش فرض مقدارشون را صفرمیگیره ، پس نباید زمانی که هر 4 تا حالت را مشخص میکنیم ، فرقی کنن . اگه صفر نگیره ، اول اینکه به نظر میاد حداقل قوانین سی شارپ را نقض کرد (حالا نمیدونم کدهای xaml ، چجوری تفسیر و تبدیل به سی شارپ میشه) و دوما در این صورت (که مقدارش را مشخص نمیکنیم) ، پس مقدار دقیقش چیه؟
nullable هم که نیستن .

منظورتون از بخشی از خونه دوم چیه؟ به نظرتون Width دکمه از 250 کمتر شده؟ کمتر نیست، کل خانه "Grid.Column="0" Grid.Row="1 رو پوشش داده.

متوجه شدم . Width ئه ColumnDefinition محدود به 250 بود که حواسم نبود .

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

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

Alignment, Margins, and Padding Overview - WPF

چرا تعریفِ Margin را این جوری میگه؟ :

کد:
The Margin property describes the distance between an element and its child or peers.

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

و همچنین توضیحات Padding را هم برعکسِ این حالت گفت (نسبت به المنت والد گفت) .
 

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

بالا