簡體   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