Раскадровка VisualState не активируется в состоянии пути MouseOver - PullRequest
0 голосов
/ 30 мая 2019

Я пытаюсь изменить цвет элемента управления Path при наведении мыши, когда данные пути всегда изменяются посредством привязки данных. Он должен измениться с желтого на красный, но на пути нет изменения цвета при наведении на него мыши, он остается желтым.

мой взгляд:

MainWindow.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>

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();


    }
}

Преобразователь

[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();
    }
}

моя модель представления: MainViewModel.cs

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);
    }
}

Ответы [ 2 ]

1 голос
/ 30 мая 2019

Согласно документации , VisualTransition сам по себе не может быть запущен только потому, что имя "MouseOver".Для выполнения перехода все еще требуется какой-либо обработчик событий.Вам необходимо добавить обработчик событий для события MouseOver, инициируемого путем.

0 голосов
/ 31 мая 2019

Я вижу, что моя ошибка заключалась в предположениях о ранее существующих именах визуальных состояний на основе различных источников, из которых я впервые узнал об использовании VisualStateManager.

Добавление следующего кода к моему представлению функционировало как ожидалось:

MainWindow.xaml.cs

    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);
    }

MainWindow.xaml

Переместить код менеджера состояний в элемент 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>
...