繁体   English   中英

通过C#访问XAML控件

[英]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;
                    }
                }
            }
        }
    }
}

创建自定义WindowUserControl ,将为其生成一个(部分)类,其中包含任何已命名子元素的字段。 但是,这不适用于样式和模板-可能是因为它们可以应用于多个控件,所以名称不一定映射到单个项目(或完全映射到一个项目)。

艰难的道路

因此,您要查找的动画是样式的一部分,而样式是窗口中的资源。 准确地说:您的样式包含一组触发器。 它的第一个触发器有一个“开始情节提要”动作,该动作保存了您感兴趣的情节提要。它将需要一些搜索和类型转换才能到达:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM