[英]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.