本文告訴大家,在后臺代碼,對 TranslateTransform 做影片的方法
今天小伙伴問我一個問題,說為什么相同的代碼,如果設定到按鈕上,是可以讓按鈕的某個屬性變更,但是如果設定給 TranslateTransform 的 X 或 Y 就不會有任何值變更
在 WPF 中,通過 官方檔案 里面的描述,對于 Freezable 型別的物件,如 SolidColorBrush 和 RotateTransform 和 GradientStop 等型別,都是不支持直接的影片,也就是如以下代碼是不能觸發影片
假定有 XAML 界面如下,期望在點擊按鈕時,修改按鈕的 TranslateTransform 做影片
<Grid>
<Button x:Name="Button" HorizontalAlignment="Center" VerticalAlignment="Center" Content="按鈕" Click="Button_OnClick">
<Button.RenderTransform>
<TranslateTransform x:Name="ButtonTranslateTransform"></TranslateTransform>
</Button.RenderTransform>
</Button>
</Grid>
如果直接對使用 Storyboard 的 SetTarget 方法給物件設定 DoubleAnimation 將會是無效的,也就是說如以下的代碼做的 TranslateTransform 影片是無效的,沒有反應的
private void Button_OnClick(object sender, RoutedEventArgs e)
{
var storyboard = new Storyboard();
var doubleAnimation = new DoubleAnimation();
Storyboard.SetTarget(doubleAnimation, ButtonTranslateTransform);
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath(TranslateTransform.XProperty));
doubleAnimation.To = 100;
doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(2));
storyboard.Children.Add(doubleAnimation);
storyboard.Begin();
}
如果想要給 Freezable 型別的物件做影片,可以通過間接的方法,也就是通過 Freezable 型別的物件所在的元素,使用點的方式寫出來具體的代碼
private void Button_OnClick(object sender, RoutedEventArgs e)
{
var storyboard = new Storyboard();
var doubleAnimation = new DoubleAnimation();
Storyboard.SetTarget(doubleAnimation, Button);
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)"));
doubleAnimation.To = 100;
doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(2));
storyboard.Children.Add(doubleAnimation);
storyboard.Begin();
}
寫法就是通過某個元素的某個屬性加上某個型別的某個屬性,如上面代碼使用的是 UIElement 的 RenderTransform 屬性,這個屬性的值的型別是 TranslateTransform 型別,設定這個型別的 X 屬性
上面的 PropertyPath 有可以換成如下方式寫
var propertyChain = new object[]
{
UIElement.RenderTransformProperty,
TranslateTransform.XProperty
};
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(0).(1)", propertyChain));
我更推薦使用這個寫法,因為這樣就不會寫錯命名
而如果只是為了修改 TranslateTransform 的 X 屬性,最簡單的寫法就是通過 BeginAnimation 的方式,如下面代碼
private void Button_OnClick(object sender, RoutedEventArgs e)
{
ButtonTranslateTransform.BeginAnimation(TranslateTransform.XProperty, new DoubleAnimation()
{
To = 100,
Duration = new Duration(TimeSpan.FromSeconds(1))
});
}
以上代碼可以看到很清真
這里的 Duration 其實可以通過 TimeSpan 轉換,而不需要創建 Duration 物件,然而在 WPF 依然定義 Duration 類的原因是為了支持 Duration.Automatic 和 Duration.Forever 特殊的定義
如果是需要有多個屬性開始做影片,不想使用 BeginAnimation 的方式,可以通過在后臺代碼用 SetTargetName 的方法指定,如下面代碼
private void Button_OnClick(object sender, RoutedEventArgs e)
{
var storyboard = new Storyboard();
var doubleAnimation = new DoubleAnimation();
Storyboard.SetTargetName(doubleAnimation, nameof(ButtonTranslateTransform));
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath(TranslateTransform.XProperty));
doubleAnimation.To = 100;
doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(2));
var storyboardName = "s" + storyboard.GetHashCode();
// 加入到字典,讓 Storyboard 和 ButtonTranslateTransform 在相同的一個 NameScope 里
Resources.Add(storyboardName, storyboard);
storyboard.Children.Add(doubleAnimation);
storyboard.Begin();
}
在后臺代碼做影片,如果使用 SetTargetName 就需要讓 Storyboard 和對應的元素在相同的一個 NameScope 里,不然將會提示 System.InvalidOperationException 不存在可決議名稱“xx”的適用名稱領域,如下面代碼
System.InvalidOperationException:“不存在可決議名稱“ButtonTranslateTransform”的適用名稱領域,”
上面代碼通過將影片加入到資源字典的方式,讓影片和元素在相同的 NameScope 而讓影片能找到元素,但是上面代碼將會在資源字典加入一個 Storyboard 而沒有釋放,如果在你的實際代碼,我推薦在影片完成之后,洗掉資源字典的影片
我特別翻了 WPF 編程寶典,發現寶典里面沒有這部分知識,也就是沒有告訴大家為什么直接給 TranslateTransform 的屬性做影片將會失效,好在官方檔案里面有說到這點
本文代碼還請到 github 或 gitee 上閱讀代碼
可以通過如下方式獲取本文的源代碼,先創建一個空檔案夾,接著使用命令列 cd 命令進入此空檔案夾,在命令列里面輸入以下代碼,即可獲取到本文的代碼
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 78f63c1c076065d1891559f5af2cb29f10a39f8b
以上使用的是 gitee 的源,如果 gitee 不能訪問,請替換為 github 的源
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
獲取代碼之后,進入 KayceefiwhearHaijanihukere 檔案夾
Storyboards Overview - WPF .NET Framework
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/288019.html
標籤:WPF
