简体   繁体   English

单元格值与ViewModel属性的WPF MVVM GridView绑定

[英]WPF MVVM GridView binding of cell values to ViewModel properties

MVVM newbie looking for a bit of guidance about datagrid binding. MVVM新手正在寻找有关数据网格绑定的一些指导。 I have difficulty with setting up the properties where I can see that the contents of a datagrid cell has changed. 我很难设置属性,在该属性中可以看到datagrid单元的内容已更改。 I started out simple and am trying to set up an updateable country list with currency codes. 我一开始很简单,正在尝试使用货币代码建立可更新的国家/地区列表。 Is there a way I can bind my grid column cells to properties in the viewmodel? 有没有一种方法可以将网格列单元格绑定到ViewModel中的属性? So far I have just introduced a property for CurrencyCode, but I never execute the setter. 到目前为止,我刚刚为CurrencyCode引入了一个属性,但是我从未执行过setter。 What am I doing wrong? 我究竟做错了什么?

Model: 模型:

using System.Linq;

using System.Collections.ObjectModel; 使用System.Collections.ObjectModel;

namespace AdminTool.DataModel.Repositories { public class AccountingRepository : BaseRepository { private AdminToolEntities entities = new AdminToolEntities(); 命名空间AdminTool.DataModel.Repositories {公共类AccountingRepository:BaseRepository {私有AdminToolEntities实体= new AdminToolEntities();

    // Country List

    public ObservableCollection<CountryData> GetCountryList()
    {
        var result = (from c in entities.Countries
                      from u in entities.Currencies.Where(u => u.ID == c.CurrencyID).DefaultIfEmpty()
                      select new CountryData { IsChanged = false,
                                               ID = c.ID,
                                               CountryName = c.CountryName,
                                               CountryCodeISO = c.CountryCodeISO,
                                               CurrencyCode = u.CurrencyCode})
                      .OrderBy(o => o.CountryName)
                      .ToList();
        return new ObservableCollection<CountryData>(result);
    }

    public void SaveCountryList(ObservableCollection<CountryData> countryList)
    {

        var result = (from l in countryList
                      from c in entities.Countries.Where(c => c.ID == l.ID)
                      from u in entities.Currencies.Where(u => u.CurrencyCode == l.CurrencyCode).DefaultIfEmpty()
                      where l.IsChanged
                      select l)
                      .ToList();
        foreach (CountryData cd in result)
        {
            Country c = (Country)entities.Countries.Where(l => l.ID == cd.ID).FirstOrDefault();
            if (c == null) // new entry
            {
                c = new Country();
                entities.Countries.Add(c);
            }
            c.CountryName = cd.CountryName;
            c.CountryCodeISO = cd.CountryCodeISO;
            c.Currency = entities.Currencies.Where(u => u.CurrencyCode == cd.CurrencyCode).FirstOrDefault();
        }
        entities.SaveChanges();
    }
}

/// <summary>
/// Data structures
/// </summary>
public class CountryData
{
    public int ID { get; set; }
    public string CountryName { get; set; }
    public string CountryCodeISO { get; set; }
    public string CurrencyCode { get; set; }
    public bool IsChanged { get; set; }
}

} }

View: 视图:

<Window x:Class="AdminTool.Desktop.View.CountryList"
    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:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:vm="clr-namespace:AdminTool.Desktop.ViewModel"
    Title="AdminTool" Height="600" Width="500">
<Window.DataContext>
    <vm:AccountingViewModel/>
</Window.DataContext>
<Grid>
    <DataGrid Name="dgCountryList" 
              ItemsSource="{Binding CountryList, Mode=TwoWay}"
              SelectedItem="{Binding Path=SelectedCountry, Mode=TwoWay}"
              HorizontalAlignment="Left" VerticalAlignment="Top" Height="450" Width="450" Margin="20,20,0,0"
              AutoGenerateColumns="False"
              SelectionMode="Single"
              SelectionUnit="FullRow"
              GridLinesVisibility="All"
              CanUserDeleteRows="True"
              CanUserAddRows="True">
        <DataGrid.RowStyle>
            <Style TargetType="{x:Type DataGridRow}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=IsChanged}" Value="true" >
                        <Setter Property="Background" Value="LightGreen" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </DataGrid.RowStyle>
        <DataGrid.Columns>
            <!--<DataGridTextColumn Header="ID" Binding="{Binding ID}" Width="50" />-->
            <DataGridTextColumn Header="Country" Binding="{Binding Path=CountryName, Mode=TwoWay}" Width="250" />
            <DataGridTextColumn Header="ISO Code" Binding="{Binding Path=CountryCodeISO, Mode=TwoWay}" Width="80" />
            <DataGridTextColumn Header="Currency" Binding="{Binding Path=CurrencyCode, Mode=TwoWay}" Width="80" />
        </DataGrid.Columns>
    </DataGrid>
    <Button Content="Save" Command="{Binding Path=SaveCommand}" IsEnabled="{Binding Path=UpdateButtonEnabled}" HorizontalAlignment="Left" Margin="223,512,0,0" VerticalAlignment="Top" Width="75"/>
    <Button Content="Cancel" Command="{Binding Path=CancelCommand}" HorizontalAlignment="Left" Margin="343,512,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>

ViewModel: 视图模型:

using System.Collections.ObjectModel;

using AdminTool.DataModel.Repositories; 使用AdminTool.DataModel.Repositories; using AdminTool.Helpers; 使用AdminTool.Helpers;

namespace AdminTool.Desktop.ViewModel { 命名空间AdminTool.Desktop.ViewModel {

public class AccountingViewModel : ViewModelBase
{

    private ObservableCollection<CountryData> _countryList;
    public ObservableCollection<CountryData> CountryList
    {
        get { return _countryList; }
        set
        {
            _countryList = value;
            RaisePropertyChanged("CountryList");
        }
    }
    private CountryData _selectedCountry;
    public CountryData SelectedCountry
    {
        get { return _selectedCountry; }
        set
        {
            _selectedCountry = value;
            RaisePropertyChanged("SelectedCountry");
        }
    }

    private string currencyCode;

    public string CurrencyCode
    {
        get { return currencyCode; }
        set {
                currencyCode = value;
                SelectedCountry.IsChanged = true;
            }
    }

    private bool updateButtonEnabled = false;
    public bool UpdateButtonEnabled
    {
        get { return updateButtonEnabled; }
        set { updateButtonEnabled = value;
              RaisePropertyChanged("UpdateButtonEnabled");
            }
    }


    #region Commands -----------------------------------------------------------------------------------
    public RelayCommand SaveCommand { get; set; }
    public RelayCommand CancelCommand { get; set; }
    #endregion

    /// <summary>
    /// Initializes a new instance of the MainViewModel class.
    /// </summary>
    public AccountingViewModel()
    {
        SaveCommand = new RelayCommand(Save);
        CancelCommand = new RelayCommand(Cancel);

        AccountingRepository repo = new AccountingRepository();
        CountryList = repo.GetCountryList();
    }

    #region Public methods -----------------------------------------------------------------------------
    void Save(object parameter)
    {
        AccountingRepository repo = new AccountingRepository();
        repo.SaveCountryList(CountryList);
    }

    void Cancel(object parameter)
    {
    }
    #endregion
}

} }

Thanks in advance for any help. 在此先感谢您的帮助。

you have to handle the property changed event: 您必须处理属性更改事件:

public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
   if (this.PropertyChanged != null)
     this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

You need to make changes in model. 您需要更改模型。 Implement notify interface as given below. 实现通知接口,如下所示。

Model - With name property being updated 模型-名称属性被更新

public class CountryData : INotifyPropertyChanged
{
    private string countryName;
    public string CountryName
    {
        get { return countryName; }
        set
        {
            countryName = value;
            RaisePropertyChanged("CountryName");
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;

    public void RaisePropertyChanged(string prop)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
        }
    }

}

View - Use UpdateSourceTrigger=PropertyChanged with Bindings in grid. 视图-将UpdateSourceTrigger=PropertyChanged与网格中的Bindings一起使用。

<Grid>
    <DataGrid Name="dgCountryList" 
          ItemsSource="{Binding CountryList, Mode=TwoWay}"
          SelectedItem="{Binding Path=SelectedCountry, Mode=TwoWay}"
          HorizontalAlignment="Left" VerticalAlignment="Top" Height="450" Width="450" Margin="20,20,0,0"
          AutoGenerateColumns="False"
          SelectionMode="Single"
          SelectionUnit="FullRow"
          GridLinesVisibility="All"
          CanUserDeleteRows="True"
          CanUserAddRows="True">
        <DataGrid.RowStyle>
            <Style TargetType="{x:Type DataGridRow}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=IsChanged}" Value="true" >
                        <Setter Property="Background" Value="LightGreen" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </DataGrid.RowStyle>
        <DataGrid.Columns>
            <!--<DataGridTextColumn Header="ID" Binding="{Binding ID}" Width="50" />-->
            <DataGridTextColumn Header="Country" Binding="{Binding Path=CountryName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="250" />

        </DataGrid.Columns>
    </DataGrid>
    <Button Content="Save" Command="{Binding Path=SaveCommand}" IsEnabled="{Binding Path=UpdateButtonEnabled}" HorizontalAlignment="Left" Margin="223,512,0,0" VerticalAlignment="Top" Width="75"/>
    <Button Content="Cancel" Command="{Binding Path=CancelCommand}" HorizontalAlignment="Left" Margin="343,512,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>

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

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