C# VisualState情节提要未在路径上激活';鼠标盖';状态
我试图改变鼠标上路径控件的颜色,因为路径数据总是通过数据绑定而改变。它应该从黄色变为红色,但当我将鼠标移到它上面时,路径上没有颜色变化,它仍然是黄色 我的观点: main window.xamlC# VisualState情节提要未在路径上激活';鼠标盖';状态,c#,wpf,reactiveui,C#,Wpf,Reactiveui,我试图改变鼠标上路径控件的颜色,因为路径数据总是通过数据绑定而改变。它应该从黄色变为红色,但当我将鼠标移到它上面时,路径上没有颜色变化,它仍然是黄色 我的观点: main window.xaml <reactiveui:ReactiveWindow x:Class="TestWpfAnim.MainWindow" x:TypeArguments="local:MainViewModel" xmlns:reactiveui="http://reactiveui.ne
<reactiveui:ReactiveWindow
x:Class="TestWpfAnim.MainWindow"
x:TypeArguments="local:MainViewModel"
xmlns:reactiveui="http://reactiveui.net"
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:TestWpfAnim"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local:PointsToPathNormalConv x:Key="MyConv" />
</Window.Resources>
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<!--Take one half second to transition to the MouseOver state.-->
<VisualTransition To="MouseOver" GeneratedDuration="0:0:0.5" />
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="MyAnimatedBrush" Storyboard.TargetProperty="Color" To="Red" Duration="0:0:0.5"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Path
x:Name="MainPath" StrokeThickness="4"
Data="{Binding Poly, Converter={StaticResource MyConv}}">
<Path.Stroke>
<SolidColorBrush Color="Yellow" x:Name="MyAnimatedBrush" />
</Path.Stroke>
</Path>
</Grid>
MainWindow.xaml.cs
public partial class MainWindow : ReactiveWindow<MainViewModel>
{
public MainWindow()
{
InitializeComponent();
ViewModel = new MainViewModel();
DataContext = ViewModel;
var timer = new DispatcherTimer(DispatcherPriority.Normal, Dispatcher.CurrentDispatcher)
{
Interval = TimeSpan.FromSeconds(2)
};
int x = 100;
int y = 100;
timer.Tick += (o, e) =>
{
ViewModel.Add(x++, y++ * 2);
};
timer.Start();
}
}
public class MainViewModel : AbstractNotifyPropertyChanged, IDisposable
{
public MainViewModel()
{
Poly = new ObservableCollection<System.Windows.Point>();
}
public void Add(int x, int y)
{
var newlist = Poly.ToList();
newlist.Add(new System.Windows.Point(x, y));
Poly = new ObservableCollection<System.Windows.Point>(newlist);
}
public void Dispose()
{
}
private ObservableCollection<System.Windows.Point> _poly;
public ObservableCollection<System.Windows.Point> Poly
{
get => _poly;
set => this.SetAndRaise(ref _poly, value);
}
}
public void Path_MouseEnter(object sender, MouseEventArgs e)
{
if (sender is FrameworkElement fe)
VisualStateManager.GoToElementState(fe, "MouseEnter", true);
}
public void Path_MouseLeave(object sender, MouseEventArgs e)
{
if (sender is FrameworkElement fe)
VisualStateManager.GoToElementState(fe, "MouseLeave", true);
}
public分部类主窗口:ReactiveWindow
{
公共主窗口()
{
初始化组件();
ViewModel=新的MainViewModel();
DataContext=ViewModel;
var timer=新调度程序(DispatcherPriority.Normal,Dispatcher.CurrentDispatcher)
{
间隔=时间间隔从秒(2)
};
int x=100;
int y=100;
计时器。滴答+=(o,e)=>
{
添加(x++,y++*2);
};
timer.Start();
}
}
转换器
[ValueConversion(typeof(IEnumerable<System.Windows.Point>), typeof(Geometry))]
public class PointsToPathNormalConv : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is IEnumerable<System.Windows.Point> points && points.Any())
{
List<LineSegment> segments = new List<LineSegment>();
foreach (var p in points)
{
segments.Add(new LineSegment(p, true));
}
PathFigure figure = new PathFigure(points.First(), segments, false); //true if closed
PathGeometry geometry = new PathGeometry();
geometry.Figures.Add(figure);
return geometry;
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
[ValueConversion(typeof(IEnumerable)、typeof(Geometry))]
公共类PointsToPathNormalConv:IValueConverter
{
公共对象转换(对象值、类型targetType、对象参数、CultureInfo区域性)
{
if(值为IEnumerable points&&points.Any())
{
列表段=新列表();
foreach(以点为单位的var p)
{
线段。添加(新线段(p,true));
}
PathFigure=新的PathFigure(points.First(),segments,false);//如果关闭,则为true
PathGeometry=新的PathGeometry();
几何。图形。添加(图形);
返回几何;
}
返回null;
}
公共对象转换回(对象值、类型targetType、对象参数、CultureInfo区域性)
{
抛出新的NotImplementedException();
}
}
我的视图模型:
MainViewModel.cs
public partial class MainWindow : ReactiveWindow<MainViewModel>
{
public MainWindow()
{
InitializeComponent();
ViewModel = new MainViewModel();
DataContext = ViewModel;
var timer = new DispatcherTimer(DispatcherPriority.Normal, Dispatcher.CurrentDispatcher)
{
Interval = TimeSpan.FromSeconds(2)
};
int x = 100;
int y = 100;
timer.Tick += (o, e) =>
{
ViewModel.Add(x++, y++ * 2);
};
timer.Start();
}
}
public class MainViewModel : AbstractNotifyPropertyChanged, IDisposable
{
public MainViewModel()
{
Poly = new ObservableCollection<System.Windows.Point>();
}
public void Add(int x, int y)
{
var newlist = Poly.ToList();
newlist.Add(new System.Windows.Point(x, y));
Poly = new ObservableCollection<System.Windows.Point>(newlist);
}
public void Dispose()
{
}
private ObservableCollection<System.Windows.Point> _poly;
public ObservableCollection<System.Windows.Point> Poly
{
get => _poly;
set => this.SetAndRaise(ref _poly, value);
}
}
public void Path_MouseEnter(object sender, MouseEventArgs e)
{
if (sender is FrameworkElement fe)
VisualStateManager.GoToElementState(fe, "MouseEnter", true);
}
public void Path_MouseLeave(object sender, MouseEventArgs e)
{
if (sender is FrameworkElement fe)
VisualStateManager.GoToElementState(fe, "MouseLeave", true);
}
公共类MainViewModel:AbstractNotifyPropertyChanged,IDisposable
{
公共主视图模型()
{
Poly=新的可观察集合();
}
公共无效添加(整数x,整数y)
{
var newlist=Poly.ToList();
添加(newsystem.Windows.Point(x,y));
Poly=新的可观察集合(newlist);
}
公共空间处置()
{
}
私人可观测集合;
公开收集
{
get=>\u poly;
set=>this.SetAndRaise(ref\u poly,value);
}
}
根据,VisualTransition本身不能仅仅因为名称为“MouseOver”而触发。它仍然需要某种类型的eventhandler来执行转换。您必须为路径触发的MouseOver事件添加eventhandler。我发现我的错误是根据我第一次学习使用VisualStateManager的各种来源对预先存在的可视状态名称进行假设 将以下代码添加到“我的视图”功能正常: MainWindow.xaml.cs
public partial class MainWindow : ReactiveWindow<MainViewModel>
{
public MainWindow()
{
InitializeComponent();
ViewModel = new MainViewModel();
DataContext = ViewModel;
var timer = new DispatcherTimer(DispatcherPriority.Normal, Dispatcher.CurrentDispatcher)
{
Interval = TimeSpan.FromSeconds(2)
};
int x = 100;
int y = 100;
timer.Tick += (o, e) =>
{
ViewModel.Add(x++, y++ * 2);
};
timer.Start();
}
}
public class MainViewModel : AbstractNotifyPropertyChanged, IDisposable
{
public MainViewModel()
{
Poly = new ObservableCollection<System.Windows.Point>();
}
public void Add(int x, int y)
{
var newlist = Poly.ToList();
newlist.Add(new System.Windows.Point(x, y));
Poly = new ObservableCollection<System.Windows.Point>(newlist);
}
public void Dispose()
{
}
private ObservableCollection<System.Windows.Point> _poly;
public ObservableCollection<System.Windows.Point> Poly
{
get => _poly;
set => this.SetAndRaise(ref _poly, value);
}
}
public void Path_MouseEnter(object sender, MouseEventArgs e)
{
if (sender is FrameworkElement fe)
VisualStateManager.GoToElementState(fe, "MouseEnter", true);
}
public void Path_MouseLeave(object sender, MouseEventArgs e)
{
if (sender is FrameworkElement fe)
VisualStateManager.GoToElementState(fe, "MouseLeave", true);
}
main window.xaml
<reactiveui:ReactiveWindow
x:Class="TestWpfAnim.MainWindow"
x:TypeArguments="local:MainViewModel"
xmlns:reactiveui="http://reactiveui.net"
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:TestWpfAnim"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local:PointsToPathNormalConv x:Key="MyConv" />
</Window.Resources>
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<!--Take one half second to transition to the MouseOver state.-->
<VisualTransition To="MouseOver" GeneratedDuration="0:0:0.5" />
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="MyAnimatedBrush" Storyboard.TargetProperty="Color" To="Red" Duration="0:0:0.5"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Path
x:Name="MainPath" StrokeThickness="4"
Data="{Binding Poly, Converter={StaticResource MyConv}}">
<Path.Stroke>
<SolidColorBrush Color="Yellow" x:Name="MyAnimatedBrush" />
</Path.Stroke>
</Path>
</Grid>
将状态管理器代码移到Path元素中。在将更改状态的路径上指定MouseEnter和MouseLeave操作
<Path
x:Name="MainPath" StrokeThickness="4"
Data="{Binding Poly, Converter={StaticResource MyConv}}"
MouseEnter="Path_MouseEnter"
MouseLeave="Path_MouseLeave">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="MouseLeave"/>
<VisualState x:Name="MouseEnter">
<Storyboard>
<ColorAnimation Storyboard.TargetName="MyAnimatedBrush" Storyboard.TargetProperty="Color" To="Red" Duration="0:0:0.5"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Path.Stroke>
<SolidColorBrush Color="Yellow" x:Name="MyAnimatedBrush" />
</Path.Stroke>
</Path>