简体   繁体   中英

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

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:

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

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.

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.

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

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:

<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:

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:

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

where the LastName property is binded in 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. Instead I need to set the SeriesCollection property setting the Values with the SelectedData.Datavalues property. 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:

<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:

private SeriesCollection _seriesCollection;

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

In XAML View:

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

I couldn't have done it without the invaluable help. Thanks everyone!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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