【发布时间】:2021-05-12 11:17:06
【问题描述】:
MainWindow 包含一个 ItemsControl,它显示来自列表集合的数据。 Name 和 ControlState 属性附加到 Text 和 VisualState 依赖属性。 VisualStateManager.GoToState() 总是返回 false。如何将视觉状态附加到依赖属性,以便执行视觉状态的更改?
Сode:
主窗口:
<Window x:Class="WpfFW.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:WpfFW"
mc:Ignorable="d"
DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"
Title="MainWindowFWTest" Height="100" Width="300">
<ItemsControl ItemsSource="{Binding list}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:UserControl1 Text="{Binding Name}" VisualState="{Binding ControlState}"
Width="200" BorderBrush="Black" BorderThickness="2" Padding="2"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
public partial class MainWindow : Window
{
public MainWindow()
{
list = new ObservableCollection<ControlData>() {
new ControlData() { Name = "Control 1", ControlState = 0 },
new ControlData() { Name = "Control 2", ControlState = 1 }};
InitializeComponent();
}
public ObservableCollection<ControlData> list { get; set; }
}
public class ControlData : INotifyPropertyChanged
{
private string _Name;
public string Name
{
get => _Name;
set
{
_Name = value;
SetProperty(nameof(Name));
}
}
private int _ControlState;
public int ControlState
{
get => _ControlState;
set
{
_ControlState = value;
SetProperty(nameof(ControlState));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void SetProperty(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
用户控制1
<UserControl x:Class="WpfFW.UserControl1"
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:WpfFW"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="Common">
<VisualState x:Name="State1">
<Storyboard>
<DoubleAnimation To="1" Duration="0:00:2" Storyboard.TargetName="State1Panel" Storyboard.TargetProperty="(UIElement.Opacity)" />
<DoubleAnimation To="0" Duration="0:00:3" Storyboard.TargetName="State2Panel" Storyboard.TargetProperty="(UIElement.Opacity)" />
</Storyboard>
</VisualState>
<VisualState x:Name="State2">
<Storyboard>
<DoubleAnimation To="0" Duration="0:00:3" Storyboard.TargetName="State1Panel" Storyboard.TargetProperty="(UIElement.Opacity)" />
<DoubleAnimation To="1" Duration="0:00:2" Storyboard.TargetName="State2Panel" Storyboard.TargetProperty="(UIElement.Opacity)" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border Name="State2Panel" Background="Green" Opacity="0"/>
<Border Name="State1Panel" Background="Red" Opacity="1"/>
<TextBlock Text="{Binding Text, RelativeSource={RelativeSource AncestorType=local:UserControl1, Mode=FindAncestor}}" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
public partial class UserControl1 : UserControl
{
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(UserControl1), new PropertyMetadata(""));
public string VisualState
{
get { return (string)GetValue(VisualStateProperty); }
set { SetValue(VisualStateProperty, value); }
}
public static readonly DependencyProperty VisualStateProperty =
DependencyProperty.Register("VisualState", typeof(string), typeof(UserControl1), new PropertyMetadata(new PropertyChangedCallback(VisualStateChanged)));
public static void VisualStateChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue != null)
{
string state = e.NewValue.ToString();
var control = o as FrameworkElement;
bool b = VisualStateManager.GoToState(control, "state" + state, true);
}
}
public UserControl1()
{
InitializeComponent();
}
}
【问题讨论】: