Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么这个MultiDataTrigger会在动画上引发异常?_C#_Wpf_Mvvm - Fatal编程技术网

C# 为什么这个MultiDataTrigger会在动画上引发异常?

C# 为什么这个MultiDataTrigger会在动画上引发异常?,c#,wpf,mvvm,C#,Wpf,Mvvm,在viewmodel上显示多个视图的WPF-MVVM应用程序。用户可以在运行时从不太详细的视图转到更详细的视图。视图包含在边框内。在一组条件下,viewmodel会触发报警。报警在视图中呈现为边框背景上闪烁颜色的动画,以吸引用户注意 问题在于,当触发报警并且用户在运行时更改数据模板以获取更多细节时,WPF引擎在使用multidatatrigger报警时会在动画上引发异常。引擎在使用Datatrigger时工作,在其他一切相同的情况下在MultiDataTrigger上崩溃 例外情况是:无法在不可

在viewmodel上显示多个视图的WPF-MVVM应用程序。用户可以在运行时从不太详细的视图转到更详细的视图。视图包含在边框内。在一组条件下,viewmodel会触发报警。报警在视图中呈现为边框背景上闪烁颜色的动画,以吸引用户注意

问题在于,当触发报警并且用户在运行时更改数据模板以获取更多细节时,WPF引擎在使用multidatatrigger报警时会在动画上引发异常。引擎在使用Datatrigger时工作,在其他一切相同的情况下在MultiDataTrigger上崩溃

例外情况是:无法在不可变对象上设置“(0)。(1)”的动画

演示问题的示例应用程序:

1个用于承载和切换视图的主窗口

2个视图,大视图和小视图

1视图模型

1个用于多个和单个datatriggers的资源字典

App.Xaml:

<Application x:Class="AnimationSample.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:AnimationSample"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary Source="Dictionary1.xaml"/>
    </Application.Resources>
</Application>

MainWindow.xaml:

<Window x:Class="AnimationSample.MainWindow"
        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:AnimationSample"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <DataTemplate DataType="{x:Type local:SampleViewModel}" x:Key="smallTemplate">
            <local:SmallUserControl />
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:SampleViewModel}" x:Key="largeTemplate">
            <local:LargeUserControl />
        </DataTemplate>        
        <DataTemplate DataType="{x:Type local:SampleViewModel}" x:Key="mainTemplate">
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding ElementName=ZoomSlider, Path=Value}" Value="1">                 
                    <Setter Property="ContentTemplate" Value="{StaticResource smallTemplate}"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding ElementName=ZoomSlider, Path=Value}" Value="2">                        
                    <Setter Property="ContentTemplate" Value="{StaticResource largeTemplate}"/>
                </DataTrigger>                
            </DataTemplate.Triggers>
        </DataTemplate>
        <Style TargetType="{x:Type ContentControl}" x:Key="DisplayStyle">
            <Setter Property="ContentTemplate" Value="{StaticResource smallTemplate}" />
            <Style.Triggers>
                <DataTrigger Binding="{Binding ElementName=ZoomSlider, Path=Value}" Value="1">
                    <Setter Property="ContentTemplate" Value="{StaticResource smallTemplate}"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding ElementName=ZoomSlider, Path=Value}" Value="2">
                    <Setter Property="ContentTemplate" Value="{StaticResource largeTemplate}"/>
                </DataTrigger>                
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <StackPanel Margin="8">
        <Slider x:Name="ZoomSlider" Minimum="1" Maximum="2" IsSnapToTickEnabled="True" />
        <ContentControl Content="{Binding}" Style="{StaticResource DisplayStyle}">
        </ContentControl>
    </StackPanel>
</Window>

MainWindow.cs:

using System.Windows;

namespace AnimationSample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new SampleViewModel();
        }
    }
}
使用System.Windows;
名称空间动画示例
{
/// 
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
DataContext=新的SampleViewModel();
}
}
}
SampleViewModel.cs:

using System;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Windows;

namespace AnimationSample
{
    public class SampleViewModel : NotifyPropertyChangedBase<SampleViewModel>
    {
        private bool _alarm;
        public bool Alarm
        {
            get { return _alarm; }
            set
            {
                if (!_alarm.Equals(value))
                {
                    _alarm = value;
                    OnPropertyChanged("Alarm");                    
                }
            }
        }

        private bool _flash;
        public bool Flash
        {
            get { return _flash; }
            set
            {
                if (!_flash.Equals(value))
                {
                    _flash = value;
                    OnPropertyChanged("Flash");
                }
            }
        }


        private string _description = "I am an alarm!";
        public string Description
        {
            get { return _description; }
            set
            {
                if(!_description.Equals(value))
                {
                    _description = value;
                    OnPropertyChanged("Description");
                }
            }
        }
    }

    public abstract class NotifyPropertyChangedBase<T> : DependencyObject, INotifyPropertyChanged
    {

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            { PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); }
        }

        protected virtual void OnPropertyChanged<T2>(Expression<Func<T, T2>> accessor)
        {
            OnPropertyChanged(PropertyName(accessor));
        }        

        public static string PropertyName<T2>(Expression<Func<T, T2>> accessor)
        {
            return ((MemberExpression)accessor.Body).Member.Name;
        }
    }
}
使用系统;
使用系统组件模型;
使用System.Linq.Expressions;
使用System.Windows;
名称空间动画示例
{
公共类SampleViewModel:NotifyPropertyChangedBase
{
私家车报警;
公共报警
{
获取{return\u alarm;}
设置
{
如果(!\u报警等于(值))
{
_报警=数值;
不动产变更(“报警”);
}
}
}
私人布卢闪光灯;
公共广播闪光灯
{
获取{return\u flash;}
设置
{
如果(!\u flash.Equals(值))
{
_闪光=数值;
OnPropertyChanged(“Flash”);
}
}
}
私有字符串_description=“我是警报!”;
公共字符串描述
{
获取{return\u description;}
设置
{
如果(!\u说明等于(值))
{
_描述=值;
不动产变更(“说明”);
}
}
}
}
公共抽象类NotifyPropertyChangedBase:DependencyObject,INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
受保护的虚拟void OnPropertyChanged(字符串propertyName)
{
if(PropertyChanged!=null)
{PropertyChanged.Invoke(这是新的PropertyChangedEventArgs(propertyName));}
}
受保护的虚拟void OnPropertyChanged(表达式访问器)
{
OnPropertyChanged(PropertyName(访问器));
}        
公共静态字符串PropertyName(表达式访问器)
{
返回((MemberExpression)accessor.Body).Member.Name;
}
}
}
字典1.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:AnimationSample">
    <Style x:Key="FlashyAlarmBorderStyle" TargetType="{x:Type Border}">
        <Setter Property="BorderBrush" Value="Silver"/>
        <Setter Property="Background" Value="Black" />
        <Setter Property="BorderThickness" Value="2" />
        <Setter Property="CornerRadius" Value="8" />
        <Style.Triggers>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding Alarm}" Value="True" />
                    <Condition Binding="{Binding Flash}" Value="True" />
                </MultiDataTrigger.Conditions>
                <Setter Property="Background" Value="Orange"/>
                <Setter Property="BorderBrush" Value="Orange"/>
                <MultiDataTrigger.EnterActions>
                    <BeginStoryboard Name="faultBoard">
                        <Storyboard>
                            <ColorAnimation AutoReverse="True" 
                                                RepeatBehavior="Forever" 
                                                Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" 
                                                Duration="00:00:01"                                            
                                                From="Silver"
                                                To="Orange"/>
                        </Storyboard>
                    </BeginStoryboard>
                </MultiDataTrigger.EnterActions>
                <MultiDataTrigger.ExitActions>
                    <StopStoryboard BeginStoryboardName="faultBoard">
                    </StopStoryboard>
                </MultiDataTrigger.ExitActions>
            </MultiDataTrigger>
            <!--<DataTrigger Binding="{Binding Alarm}" Value="True" >
                <Setter Property="Background" Value="Orange"/>
                <Setter Property="BorderBrush" Value="Orange"/>
                <DataTrigger.EnterActions>
                    <BeginStoryboard Name="alarmBoard">
                        <Storyboard>
                            <ColorAnimation AutoReverse="True" 
                                                RepeatBehavior="Forever" 
                                                Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" 
                                                Duration="00:00:01"                                            
                                                From="Silver"
                                                To="Orange"/>
                        </Storyboard>
                    </BeginStoryboard>
                </DataTrigger.EnterActions>
                <DataTrigger.ExitActions>
                    <StopStoryboard BeginStoryboardName="alarmBoard">
                    </StopStoryboard>
                </DataTrigger.ExitActions>
            </DataTrigger>-->          
        </Style.Triggers>
    </Style>
</ResourceDictionary>

LargeUserControl.xaml:

<UserControl x:Class="AnimationSample.LargeUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:AnimationSample"
             mc:Ignorable="d" >
    <Border Margin="8"
            Style="{DynamicResource FlashyAlarmBorderStyle}">
        <StackPanel>
            <Label HorizontalAlignment="Center" Content="LARGE VIEW" Foreground="White"/>
            <CheckBox Margin="8" IsChecked="{Binding Alarm}" Content="Turn on the alarm." Foreground="White" />
            <CheckBox Margin="8"  IsChecked="{Binding Flash}" Content="Turn on the flash!" Foreground="White" />
            <Label Margin="8" Content="{Binding Description}" Foreground="White"/>
        </StackPanel>
    </Border>
</UserControl>
<UserControl x:Class="AnimationSample.SmallUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:AnimationSample"
             mc:Ignorable="d" >
    <Border Margin="8"
            Style="{DynamicResource FlashyAlarmBorderStyle}">
        <StackPanel>
            <Label HorizontalAlignment="Center" Content="SMALL VIEW" Foreground="White"/>
            <CheckBox Margin="4" IsChecked="{Binding Alarm}" Content="Turn on the alarm." HorizontalAlignment="Center" Foreground="White" />
            <CheckBox Margin="4" IsChecked="{Binding Flash}" Content="Turn on the flash!" HorizontalAlignment="Center" Foreground="White" />
        </StackPanel>
    </Border>
</UserControl>

SmallUserControl.xaml:

<UserControl x:Class="AnimationSample.LargeUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:AnimationSample"
             mc:Ignorable="d" >
    <Border Margin="8"
            Style="{DynamicResource FlashyAlarmBorderStyle}">
        <StackPanel>
            <Label HorizontalAlignment="Center" Content="LARGE VIEW" Foreground="White"/>
            <CheckBox Margin="8" IsChecked="{Binding Alarm}" Content="Turn on the alarm." Foreground="White" />
            <CheckBox Margin="8"  IsChecked="{Binding Flash}" Content="Turn on the flash!" Foreground="White" />
            <Label Margin="8" Content="{Binding Description}" Foreground="White"/>
        </StackPanel>
    </Border>
</UserControl>
<UserControl x:Class="AnimationSample.SmallUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:AnimationSample"
             mc:Ignorable="d" >
    <Border Margin="8"
            Style="{DynamicResource FlashyAlarmBorderStyle}">
        <StackPanel>
            <Label HorizontalAlignment="Center" Content="SMALL VIEW" Foreground="White"/>
            <CheckBox Margin="4" IsChecked="{Binding Alarm}" Content="Turn on the alarm." HorizontalAlignment="Center" Foreground="White" />
            <CheckBox Margin="4" IsChecked="{Binding Flash}" Content="Turn on the flash!" HorizontalAlignment="Center" Foreground="White" />
        </StackPanel>
    </Border>
</UserControl>

如果运行代码并单击报警和闪烁复选框,则控件将从黑色背景的银色边框变为闪烁的橙色。如果将滑块从小视图移动到大视图,则如果使用multidatatrigger,将从wpf获得运行时。如果在Dictionar1.xaml中取消对datatrigger的注释,并对multidatatrigger进行注释,然后重复上述操作,则应用程序运行正常

为什么DataTemplate上的multidatatrigger gag发生了变化,datatrigger工作正常?与单个datatrigger的唯一区别是增加了一个布尔值。怎么能修好呢


(是的,可以通过在viewmodel上创建一个属性来聚合这些布尔值来解决问题,但这不必这样做,也不存在问题。这似乎是wpf的一个bug?

删除设置与您尝试设置动画的相同属性(
背景
)的setter:

<MultiDataTrigger>
    <MultiDataTrigger.Conditions>
        <Condition Binding="{Binding Alarm}" Value="True" />
        <Condition Binding="{Binding Flash}" Value="True" />
    </MultiDataTrigger.Conditions>
    <!--<Setter Property="Background" Value="Orange"/>-->
    <Setter Property="BorderBrush" Value="Orange"/>
    <MultiDataTrigger.EnterActions>
        <BeginStoryboard Name="faultBoard">
            <Storyboard>
                <ColorAnimation AutoReverse="True" 
                                RepeatBehavior="Forever" 
                                Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" 
                                Duration="00:00:01"                                            
                                From="Silver"
                                To="Orange"/>
            </Storyboard>
        </BeginStoryboard>
    </MultiDataTrigger.EnterActions>
    <MultiDataTrigger.ExitActions>
        <StopStoryboard BeginStoryboardName="faultBoard">
        </StopStoryboard>
    </MultiDataTrigger.ExitActions>
</MultiDataTrigger>


有什么例外?无法在不可变对象上设置“(0)。(1)”的动画。这对我来说是正确的!不知道我抽的是什么…谢谢你的评论!