简体   繁体   English

如何在 UI 中的属性更改时引发事件

[英]How to raise an event when a Property changes in the UI

I'll do my best to explain in detail what I'm trying to do.我会尽力详细解释我正在尝试做的事情。

I'm working with Caliburn.Micro Framework in a WPF project.我在 WPF 项目中使用 Caliburn.Micro 框架。 I have a Model Class called DataModel which have two properties, Tag which is a string and DataValues which is a List of double values:我有一个名为 DataModel 的 Model Class 有两个属性,Tag 是一个字符串,DataValues 是一个双值列表:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WPFUI.Models
{
    public class DataModel
    {
        public string Tag { get; set; }
        public List<double> DataValues { get; set; }
    }
}

I added a Combobox to the View where it's Items are all the Tags of some created objects of DataModel Class as a BindableCollection Property in the ViewModel:我在视图中添加了 Combobox,其中的项目是 DataModel Class 的一些创建对象的所有标签,作为 ViewModel 中的 BindableCollection 属性:

private BindableCollection<DataModel> _data = new BindableCollection<DataModel>();

public BindableCollection<DataModel> Data
        {
            get { return _data; }
            set { _data= value; }
        }

And in UI:在用户界面中:

<ComboBox x:Name="Data" DisplayMemberPath="Tag" />

The BindableCollection is generated from each DataColumn of a DataTable (each column of the table is an object where the Header is the Tag Property of string type and row values are the DataValues Property of List type). BindableCollection 是从 DataTable 的每个 DataColumn 生成的(表的每一列都是 object,其中 Header 是字符串类型的 Tag 属性,行值是 List 类型的 DataValues 属性)。

What I'm looking for is to create a Property called SelectedData in ViewModel that notifies changes of the Selection in the Combobox to the ViewModel and then access to the DataValues Property of the SelectedItem to pass that List to a Chart Values (I'm using LiveCharts ) that sets a SeriesCollection Property that are linked to the UI.我正在寻找的是在 ViewModel 中创建一个名为 SelectedData 的属性,它将 Combobox 中的选择更改通知给 ViewModel,然后访问 SelectedItem 的 DataValues 属性以将该列表传递给图表值(我正在使用LiveCharts ) 设置链接到 UI 的 SeriesCollection 属性。

Something like this:像这样的东西:

private DataModel _selectedData;
public DataModel SelectedData
        {
            get { return _selectedData; }
            set
            {
                _selectedData= value;
                NotifyOfPropertyChange(() => SelectedData);
            }
        }

// Code to handle the DataObject selected in the Combobox 
SeriesCollection = new SeriesCollection
        {
            new LineSeries
            {
                Title = DataObject.Tag,
                Values = DataObject.DataValues.AsChartValues() // LiveCharts
            },
        };
//

public SeriesCollection SeriesCollection { get; set; }

Note: SeriesCollection must implement NotifyPropertyChanged in order to notify the UI the change of the Property.注意: SeriesCollection 必须实现 NotifyPropertyChanged 才能通知 UI 属性的变化。

Summary概括

In other words what I'm trying to do is notify the source that a Property change in the UI and then manipulate the DataObject (which is defined with the SelectedItem of the Combobox) inside the ViewModel to show new data in the UI (notifying changes in SeriesCollection Property).换句话说,我要做的是通知源 UI 中的属性更改,然后在 ViewModel 中操作 DataObject(使用 Combobox 的 SelectedItem 定义)以在 UI 中显示新数据(通知更改在 SeriesCollection 属性中)。

How can I do to achieve this?我该怎么做才能做到这一点?

EDIT编辑

If there is a PersonModel Class with FirstName and LastName properties instead of a DataModel Class, something like the following could be done in the View:如果存在具有 FirstName 和 LastName 属性的 PersonModel Class 而不是 DataModel Class,则可以在视图中执行以下操作:

<ComboBox Grid.Row="3" Grid.Column="1" x:Name="People"
                  SelectedItem="{Binding Path=SelectedPerson, Mode=OneWayToSource}"
                  DisplayMemberPath="FirstName" />
        <TextBlock Grid.Row="3" Grid.Column="2" x:Name="SelectedPerson_LastName" />

And in the ViewModel:在 ViewModel 中:

public BindableCollection<PersonModel> People
        {
            get { return _people; }
            set { _people = value; }
        }

        public PersonModel SelectedPerson
        {
            get { return _selectedPerson; }
            set
            {
                _selectedPerson = value;
                NotifyOfPropertyChange(() => SelectedPerson);
            }
        }

Then any time you change the selection of the Combobox the text of the TextBlock will update due to the line:然后,每当您更改 Combobox 的选择时,TextBlock 的文本将由于以下行而更新:

<TextBlock Grid.Row="3" Grid.Column="2" x:Name="SelectedPerson_LastName" />

where the LastName property is binded in x:Name="SelectedPerson_LastName"其中 LastName 属性绑定在x:Name="SelectedPerson_LastName"

I'm trying to implement a similar approach but I can't make x:Name="SelectedData_DataValues" directly in order to update the chart.我正在尝试实施类似的方法,但我不能直接使x:Name="SelectedData_DataValues"来更新图表。 Instead I need to set the SeriesCollection property setting the Values with the SelectedData.Datavalues property.相反,我需要设置 SeriesCollection 属性,使用 SelectedData.Datavalues 属性设置值。 But that's exactly what I don't know how to do.但这正是我不知道该怎么做的。

Well, finally i got it:好吧,我终于明白了:

private DataModel _selectedData;

public DataModel SelectedData
        {
            get { return _selectedData; }
            set
            {
                _selectedData = value;
                NotifyOfPropertyChange(() => SelectedData);

                if (SelectedData != null)
                {
                    SeriesCollection = new SeriesCollection
                    {
                        new LineSeries
                        {
                            Title = SelectedData.Tag,
                            Values = SelectedData.DataValues.AsChartValues()
                        },
                    };
                }  
            }
        }

In XAML View:在 XAML 查看:

<ComboBox Grid.Row="1" Grid.Column="1" Width="100" x:Name="Data"
                  SelectedItem="{Binding Path=SelectedData, Mode=OneWayToSource}"
                  DisplayMemberPath="Tag" />

And now SeriesCollection Property must implement NotifyPropertyChanged:现在 SeriesCollection 属性必须实现 NotifyPropertyChanged:

private SeriesCollection _seriesCollection;

public SeriesCollection SeriesCollection
        {
            get { return _seriesCollection; }
            set {
                    _seriesCollection = value;
                    NotifyOfPropertyChange(() => SeriesCollection);
                }
        }

In XAML View:在 XAML 查看:

<lvc:CartesianChart Series="{Binding SeriesCollection}">

I couldn't have done it without the invaluable help.没有宝贵的帮助,我无法做到。 Thanks everyone!感谢大家!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM