加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – WPF路径绑定到PointCollection而不更新UI

发布时间:2020-12-15 22:01:19 所属栏目:百科 来源:网络整理
导读:我正在尝试学习MVVM样式更新.不是那么游泳. 我不得不更新一个基于对Point Collection的更改而绘制的简单矩形. 在初始化时,UI更新,但在对Point Collection进行简单更改后,UI中的路径不会更新. 我添加了一些TextBlock来确保Change事件被触发,但此时我有点迷失.
我正在尝试学习MVVM样式更新.不是那么游泳.

我不得不更新一个基于对Point Collection的更改而绘制的简单矩形.
在初始化时,UI更新,但在对Point Collection进行简单更改后,UI中的路径不会更新.

我添加了一些TextBlock来确保Change事件被触发,但此时我有点迷失.

任何帮助赞赏:

XAML:

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:ExampleGreg" x:Class="ExampleGreg.MainWindow"
        Title="MainWindow" Height="161.614" Width="324.087">
    <Grid x:Name="gridUser" MouseDown="click_MouseDown" >
        <Canvas x:Name="MeterCanvas" Margin="14,7,30,0" Background="#FFAFAFAF" Height="35" VerticalAlignment="Top">
            <Path Stroke="Black" StrokeThickness="2">
                <Path.Data>
                    <PathGeometry x:Name="geometry"/>
                </Path.Data>
            </Path>
            <Path Stroke="Black" StrokeThickness="2">
                <Path.Data>
                    <PathGeometry x:Name="polylinePwr">
                        <PathGeometry.Transform>
                            <ScaleTransform ScaleX="{Binding ActualWidth,ElementName=MeterCanvas}" ScaleY="{Binding ActualHeight,ElementName=MeterCanvas}" />
                        </PathGeometry.Transform>
                        <PathGeometry.Figures>
                            <PathFigure IsClosed ="True" StartPoint="{Binding Path=thePoints[0]}">
                                <PathFigure.Segments>
                                    <PathSegmentCollection>
                                        <PolyLineSegment Points="{Binding thePoints,UpdateSourceTrigger=PropertyChanged}" />
                                    </PathSegmentCollection>
                                </PathFigure.Segments>
                            </PathFigure>
                        </PathGeometry.Figures>
                    </PathGeometry>
                </Path.Data>
            </Path>
        </Canvas>
        <Label Content="{Binding thePoints[0]}" Margin="14,58,199.6,0" VerticalAlignment="Top" Height="30" BorderThickness="1"/>
        <Label Content="{Binding thePoints[1]}" Margin="14,88,0" VerticalAlignment="Top" Height="30" BorderThickness="1"/>
        <Label Content="{Binding thePoints[2]}" Margin="165,29.6,0" VerticalAlignment="Top" Height="30" BorderThickness="1"/>
        <Label Content="{Binding thePoints[3]}" Margin="165,93,0" VerticalAlignment="Top" Height="30" BorderThickness="1"/>
    </Grid>
</Window>

主窗口:

public partial class MainWindow : Window
{
    private MainViewModel mvm;
    public MainWindow()
    {
        InitializeComponent();
        mvm = new MainViewModel();
        this.DataContext = mvm;

    }

    private void click_MouseDown(object sender,MouseButtonEventArgs e)
    {
        mvm.theText = mvm.theText + ".";
        mvm.ChangePoint(.4);
    }
}

模型视图:

class MainViewModel : INotifyPropertyChanged
{
    private string _theText = "Initial";
    private PointCollection _points = new PointCollection();
    private PolyLineSegment segment;

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(String info)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this,new PropertyChangedEventArgs(info));
        }
    }
    public MainViewModel()
    {
        ChangePoint(0.9);
    }

    public string theText
    {
        get { return _theText; }
        set
        {
            if (_theText != value)
            {
                _theText = value;
                OnPropertyChanged("theText");
            }
        }
    }
    public PointCollection thePoints
    {
        get
        { return _points; }
    }

    public void ChangePoint(double x)
    {
        _points.Clear();
        AddPoint(new Point(0.2,0.2));
        AddPoint(new Point(0.2,0.8));
        AddPoint(new Point(x,0.2));

        OnPropertyChanged("thePoints");
        _theText = _theText + "!";
        OnPropertyChanged("theText");


    }

    public void AddPoint(Point p)
    {
        _points.Add(p);
    }
}

谢谢你的任何建议(工作:))

– 以下的答案 –
我添加了一个IValueConverter类:

public class PointCollectionConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value,System.Type targetType,object parameter,System.Globalization.CultureInfo culture)
    {
        if (value.GetType() == typeof(ObservableCollection<Point>) && targetType == typeof(PointCollection))
        {
            var pointCollection = new PointCollection();
            foreach (var point in value as ObservableCollection<Point>)
                pointCollection.Add(point);
            return pointCollection;
        }
        return null;

    }

    public object ConvertBack(object value,System.Globalization.CultureInfo culture)
    {
        return null; //not needed
    }

    #endregion
}

并将ModelView更改为使用Observable Collection …
更新了ModelView:

class MainViewModel : INotifyPropertyChanged
{
    private string _theText = "Initial";
    private ObservableCollection<Point> _points;
    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(String info)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this,new PropertyChangedEventArgs(info));
        }
    }

    public MainViewModel()
    {
        _points = new ObservableCollection<Point>();
        _points.Add(new Point(0.2,0.2));
        _points.Add(new Point(0.2,0.8));
    }

    public string theText
    {
        get { return _theText; }
        set
        {
            if (_theText != value)
            {
                _theText = value;
                OnPropertyChanged("theText");
            }
        }
    }
    public ObservableCollection<Point> thePoints
    {
        get
        { return _points; }
    }

    double xAdder = 0;
    double y = 0.0;
    public void ChangePoint(double x)
    {
        y = y + .1;
        if (y > .9) { y = .1; xAdder += .1; }
        _points.Add(new Point(x+xAdder,y));
        OnPropertyChanged("thePoints");

        _theText = _theText + "!";
        OnPropertyChanged("theText");

    }

}

并更新了XAML:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ExampleGreg"  x:Class="ExampleGreg.MainWindow"
    Title="MainWindow" Height="161.614" Width="324.087">
<Window.Resources>
    <local:PointCollectionConverter x:Key="pointCollectionConverter"/>
</Window.Resources>
<Grid x:Name="gridUser" MouseDown="click_MouseDown" >
    <Canvas x:Name="MeterCanvas" Margin="14,0" Background="#FFAFAFAF" Height="35" VerticalAlignment="Top">
        <Path Stroke="Black" StrokeThickness="2">
            <Path.Data>
                <PathGeometry x:Name="geometry"/>
            </Path.Data>
        </Path>
        <Path Stroke="Black" StrokeThickness="2">
            <Path.Data>
                <PathGeometry x:Name="polylinePwr">
                    <PathGeometry.Transform>
                        <ScaleTransform ScaleX="{Binding ActualWidth,ElementName=MeterCanvas}" />
                    </PathGeometry.Transform>
                    <PathGeometry.Figures>
                        <PathFigure StartPoint="{Binding Path=thePoints[0],Converter={StaticResource pointCollectionConverter}}">
                            <PathFigure.Segments>
                                <PathSegmentCollection>
                                    <PolyLineSegment Points="{Binding thePoints,Converter={StaticResource pointCollectionConverter}}" />
                                </PathSegmentCollection>
                            </PathFigure.Segments>
                        </PathFigure>
                    </PathGeometry.Figures>
                </PathGeometry>
            </Path.Data>
        </Path>
    </Canvas>
    <Label Content="{Binding thePoints[0]}" Margin="14,0" VerticalAlignment="Top" Height="30" BorderThickness="1"/>
    <Label Content="{Binding thePoints[1]}" Margin="14,0" VerticalAlignment="Top" Height="30" BorderThickness="1"/>
    <Label Content="{Binding thePoints[2]}" Margin="165,0" VerticalAlignment="Top" Height="30" BorderThickness="1"/>
    <Label Content="{Binding thePoints[3]}" Margin="165,0" VerticalAlignment="Top" Height="30" BorderThickness="1"/>
</Grid>

鉴于IValueConverter创建了一个新的PointCollection,我不确定我是否会获得任何性能提升.每个ObservableCollection都会被更改.

感谢大家帮助我完成这项工作.我希望将完整的代码粘贴为有效,如果有其他人遇到同样的事情.

编辑#2 – 在Observable w / IValueConverter与Copying PointCollection对新PointCollection进行基准测试后,Point Collection看起来更快:

// Option 2 - WAY Faster.
    // Just Use a Points Collection,copy it,and add a point.
    public void AddPoint2(Point pt)
    {
        PointCollection pc = new PointCollection(_points2);
        pc.Add(new Point(pt.X,pt.Y));
        _points2 = pc;
        OnPropertyChanged("thePoints2");
    }

来自

// 5000 point sinwave for testing
            foreach (Point pt in sinWave) mvm.AddPoint2(pt);
            x++;

如果有更好的方式,评论赞赏.

解决方法

尝试替换属性,而不是清除重新填充它.

public void ChangePoint(double x)
{
    var newPoints = new PointCollection();
    newPoints.Add(new Point(0.2,0.2));
    newPoints.Add(new Point(0.2,0.8));
    newPoints.Add(new Point(x,0.2));

    OnPropertyChanged("thePoints");
    _theText = _theText + "!";
    OnPropertyChanged("theText");
}

如果对象引用相同,绑定似乎有时会忽略“PropertyChanged”事件.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读