[英]Access XAML Control through C#
我有一些帶有x:Name
TextBlocks
,我可以使用C#輕松訪問此控件。 但是我也有一些帶有x:Name
DoubleAnimations
,但無法訪問它們,為什么?
我已經嘗試過了,但是它不起作用,我收到一條錯誤消息,說“ Object reference not set to an instance of an object
:
//Add completed methods
DoubleAnimation da1 = (DoubleAnimation)Resources["storyboardLoad"];
da1.Completed += DoubleAnimationCompleted;
Notifications.xaml
<Window x:Class="PhotoManagement.Views.Notification"
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:PhotoManagement.Views"
mc:Ignorable="d"
Title="NotificationWindow" WindowStyle="None" AllowsTransparency="True" Background="Transparent" Width="350" SizeToContent="Height">
<Window.Resources>
<FontFamily x:Key="FontAwesome">/Fonts/#FontAwesome</FontFamily>
<SolidColorBrush x:Key="colour1" Color="#29a1d5"/>
<SolidColorBrush x:Key="colour2" Color="#248eb8"/>
<Style TargetType="StackPanel">
<Setter Property="Margin" Value="20" />
</Style>
<Style TargetType="TextBlock">
<Setter Property="TextWrapping" Value="Wrap" />
<Setter Property="Margin" Value="5" />
</Style>
<Style x:Key="NotificationIcon" TargetType="Border">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Background" Value="{DynamicResource colour2}" />
<Style.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontFamily" Value="{StaticResource FontAwesome}" />
<Setter Property="Foreground" Value="White" />
<Setter Property="FontSize" Value="28" />
<Setter Property="Padding" Value="15" />
</Style>
</Style.Resources>
</Style>
<Style x:Key="NotificationText" TargetType="Border">
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Background" Value="{DynamicResource colour1}" />
<Style.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="White" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
</Style.Resources>
</Style>
<Style x:Key="NotificationContainer" TargetType="Grid">
<!-- Animation -->
<Style.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard x:Name="StoryboardLoad">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.Opacity)"
From="0.0"
To="1.0"
Duration="0:0:0.5"/>
<DoubleAnimation x:Name="storyboardLoad" Storyboard.TargetProperty="(UIElement.Opacity)"
From="1.0"
To="0.0"
Duration="0:0:1"
BeginTime="0:0:2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<EventTrigger.Actions>
<RemoveStoryboard BeginStoryboardName="StoryboardLoad"/>
<RemoveStoryboard BeginStoryboardName="StoryboardFade"/>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<BeginStoryboard x:Name="StoryboardFade">
<Storyboard>
<DoubleAnimation x:Name="storyboardFade"
Storyboard.TargetProperty="(UIElement.Opacity)"
From="1.0"
To="0.0"
Duration="0:0:1"
BeginTime="0:0:2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid Style="{StaticResource NotificationContainer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="1"
CornerRadius="0 5 5 0"
Style="{StaticResource NotificationText}">
<TextBlock Text="A request has been added!"
x:Name="NotificationText"/>
</Border>
<Border Grid.Column="0"
CornerRadius="5 0 0 5"
Style="{StaticResource NotificationIcon}">
<TextBlock Text=""
x:Name="NotificationIcon"/>
</Border>
</Grid>
<Grid.RenderTransform>
<ScaleTransform ScaleY="1" />
</Grid.RenderTransform>
</Grid>
</Window>
Notifications.xaml.cs
using System;
using System.Windows;
namespace PhotoManagement.Views
{
/// <summary>
/// Interaction logic for Notification.xaml
/// </summary>
public partial class Notification : Window
{
public Notification() : base()
{
InitializeComponent();
//Move other windows down when closed
this.Closed += this.NotificationWindowClosed;
//Get object properties
this.NotificationText.Text = "Hello";
this.NotificationIcon.Text = "G";
}
/// <summary>
/// Show the Notification and setup it's content and actions
/// </summary>
public new void Show()
{
this.Topmost = true;
this.Owner = System.Windows.Application.Current.MainWindow;
this.Closed += this.NotificationWindowClosed;
base.Show();
//Add completed methods
//Position the Notification
var workingArea = SystemParameters.WorkArea;
this.Left = (workingArea.Width - this.ActualWidth) / 2;
double top = workingArea.Bottom - this.ActualHeight - 5;
//Ensure new notifications are placed above older ones
foreach (Window window in System.Windows.Application.Current.Windows)
{
string windowName = window.GetType().Name;
if (windowName.Equals("Notification") && window != this)
{
window.Topmost = true;
top = window.Top - window.ActualHeight - 5;
}
}
this.Top = top;
}
private void ImageMouseUp(object sender,
System.Windows.Input.MouseButtonEventArgs e)
{
this.Close();
}
/// <summary>
/// Close window once animation is complete
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void DoubleAnimationCompleted(object sender, EventArgs e)
{
if (!this.IsMouseOver)
{
this.Close();
}
}
/// <summary>
/// Move the next notification down once notification has closed
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void NotificationWindowClosed(object sender, EventArgs e)
{
foreach (Window window in System.Windows.Application.Current.Windows)
{
string windowName = window.GetType().Name;
if (windowName.Equals("NotificationWindow") && window != this)
{
// Adjust any windows that were above this one to drop down
if (window.Top < this.Top)
{
window.Top = window.Top + this.ActualHeight;
}
}
}
}
}
}
創建自定義Window
或UserControl
,將為其生成一個(部分)類,其中包含任何已命名子元素的字段。 但是,這不適用於樣式和模板-可能是因為它們可以應用於多個控件,所以名稱不一定映射到單個項目(或完全映射到一個項目)。
艱難的道路
因此,您要查找的動畫是樣式的一部分,而樣式是窗口中的資源。 准確地說:您的樣式包含一組觸發器。 它的第一個觸發器有一個“開始情節提要”動作,該動作保存了您感興趣的情節提要。它將需要一些搜索和類型轉換才能到達:
Style style = (Style)Resources["NotificationContainer"];
EventTrigger trigger = (EventTrigger)style.Triggers[0];
BeginStoryboard beginStoryboard = (BeginStoryboard)trigger.Actions[0];
Storyboard storyboard = beginStoryboard.Storyboard;
如您所見,這非常脆弱。 打破它所需要做的就是重新排列XAML中的事件觸發器...
簡單的方法
但是為什么仍要查找該情節提要? 只需將其Completed
事件直接綁定到XAML中的事件處理程序即可:
<Storyboard Completed="WindowLoadedStoryboard_Completed">
...
</Storyboard>
遺憾的是,由於"The event 'Completed' cannot be specified on a Target tag in a Style. Use an EventSetter instead."
錯誤。 而且EventSetter
無法正常工作,因為Storyboard.Completed
不是路由事件...
幸運的是,您可以通過將情節提要板本身作為資源,並在begin-storyboard動作中引用它來解決此問題:
<Resources>
<Storyboard x:Key="WindowLoadedStoryboard" Completed="WindowLoadedStoryboard_Completed">
...
</Storyboard>
<Style ...>
...
<BeginStoryboard Storyboard="{StaticResource WindowLoadedStoryboard}" />
...
</Style>
</Resources>
順便說一句,這也將使查找故事板更容易,更可靠。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.