将WPF DataGridComboBoxColumn绑定到MVVM [英] Binding a WPF DataGridComboBoxColumn with MVVM

查看:1169
本文介绍了将WPF DataGridComboBoxColumn绑定到MVVM的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已查看各种答案 问题,但没有设法将问题的答案中的内容映射到我试图解决。我已经将其简化为以下代码(代表我想要实现的结果),并且基本上希望能够将 Person.TitleId 呈现为当行未被编辑时,相应的 Title.TitleText ,并且正确地下拉绑定,以便显示 TitleText s在下拉菜单中,并将关联的 TitleId 写入 Person 记录更改时。 / p>

简而言之,我如何把我的< DataGridComboBoxColumn> 实现这一点?



App.xaml.cs

  protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);

var viewModel = new ViewModels.MainWindowViewModel();
var mainWindow = new MainWindow();
mainWindow.DataContext = viewModel;
mainWindow.ShowDialog();
}

MainWindow.xaml

 < Grid> 
< DataGrid AutoGenerateColumns =FalseItemsSource ={Binding Path = Contacts}>
< DataGrid.Columns>
< DataGridComboBoxColumn Header =TitleSelectedItemBinding ={Binding Person}>
< DataGridComboBoxColumn.ElementStyle>
< Style TargetType =ComboBox>
< Setter Property =ItemsSourceValue ={Binding RelativeSource = {RelativeSource FindAncestor,AncestorType = {x:Type Window}},Path = DataContext.Titles}/>
< Setter Property =IsReadOnlyValue =True/>
< / Style>
< /DataGridComboBoxColumn.ElementStyle>
< DataGridComboBoxColumn.EditingElementStyle>
< Style TargetType =ComboBox>
< Setter Property =ItemsSourceValue ={Binding RelativeSource = {RelativeSource FindAncestor,AncestorType = {x:Type Window}},Path = DataContext.Titles}/>
< Setter Property =DisplayMemberPathValue =TitleText/>
< / Style>
< /DataGridComboBoxColumn.EditingElementStyle>
< / DataGridComboBoxColumn>
< /DataGrid.Columns>
< / DataGrid>
< / Grid>

Person.cs

  public class Person 
{
public int TitleId {get;组; }
public string LastName {get;组; }
public string FirstName {get;组; }
}

Title.cs

  public struct Title 
{
public Title(int titleId,string titleText)
:this()
{
TitleId = titleId;
TitleText = titleText;
}

public string TitleText {get;私人集合}
public int TitleId {get;私人集合}

public static List< Title> GetAvailableTitles()
{
var titles = new List< Title>();

titles.Add(new Title(1,Mr));
titles.Add(new Title(2,Miss));
titles.Add(new Title(3,Mrs));

返回标题;
}
}

MainWindowViewModel.cs

  public class MainWindowViewModel:ViewModelBase 
{
private ObservableCollection< Person>联系人
private List< Title>标题

public MainWindowViewModel()
{
titles = Title.GetAvailableTitles();

Contacts = new ObservableCollection< Person>();
Contacts.Add(new Person(){FirstName =Jane,LastName =Smith,TitleId = 2});
}

public List< Title>标题
{
get {return titles; }
}

public ObservableCollection< Person>联系人
{
get {return contacts;
set
{
if(contacts!= value)
{
contacts = value;
this.OnPropertyChanged(Contacts);
}
}
}
}

ViewModelBase .cs

  public class ViewModelBase:INotifyPropertyChanged 
{
protected void OnPropertyChanged(string propertyName)
{
if(PropertyChanged!= null)
PropertyChanged(this,new PropertyChangedEventArgs(propertyName));
}

public event PropertyChangedEventHandler PropertyChanged;
}


解决方案

这是一个工作代码。这里的关键是使用 SelectedValueBinding 而不是 SelecteItemBinding

 < DataGridComboBoxColumn Header =Title
SelectedValueBinding ={Binding TitleId}
SelectedValuePath = TitleId
DisplayMemberPath =TitleText
>
< DataGridComboBoxColumn.ElementStyle>
< Style TargetType =ComboBox>
< Setter Property =ItemsSourceValue ={Binding RelativeSource = {RelativeSource FindAncestor,AncestorType = {x:Type Window}},Path = DataContext.Titles}/>
< / Style>
< /DataGridComboBoxColumn.ElementStyle>
< DataGridComboBoxColumn.EditingElementStyle>
< Style TargetType =ComboBox>
< Setter Property =ItemsSourceValue ={Binding RelativeSource = {RelativeSource FindAncestor,AncestorType = {x:Type Window}},Path = DataContext.Titles}/>
< / Style>
< /DataGridComboBoxColumn.EditingElementStyle>
< / DataGridComboBoxColumn>


I've looked at the answers to various questions, but haven't managed to map the content in the answers to the problem I'm attempting to solve. I've reduced it down to the following code (representative of the outcome I'm trying to achieve), and basically want to be able to render the Person.TitleId as its corresponding Title.TitleText when the row isn't being edited, and have the drop-down bound correctly so that it displays the TitleTexts in the drop-down and writes the associated TitleId back to the Person record when its changed.

In short, what do I put in my <DataGridComboBoxColumn> to achieve this?

App.xaml.cs

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);

    var viewModel = new ViewModels.MainWindowViewModel();
    var mainWindow = new MainWindow();
    mainWindow.DataContext = viewModel;
    mainWindow.ShowDialog();
}

MainWindow.xaml

<Grid>
    <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Path=Contacts}">
        <DataGrid.Columns>
            <DataGridComboBoxColumn Header="Title" SelectedItemBinding="{Binding Person}">
                <DataGridComboBoxColumn.ElementStyle>
                    <Style TargetType="ComboBox">
                        <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Titles}"/>
                        <Setter Property="IsReadOnly" Value="True"/>
                    </Style>
                </DataGridComboBoxColumn.ElementStyle>
                <DataGridComboBoxColumn.EditingElementStyle>
                    <Style TargetType="ComboBox">
                        <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Titles}"/>
                        <Setter Property="DisplayMemberPath" Value="TitleText" />
                    </Style>
                </DataGridComboBoxColumn.EditingElementStyle>
            </DataGridComboBoxColumn>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

Person.cs

public class Person
{
    public int TitleId { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
}

Title.cs

public struct Title
{
    public Title(int titleId, string titleText)
        : this()
    {
        TitleId = titleId;
        TitleText = titleText;
    }

    public string TitleText { get; private set; }
    public int TitleId { get; private set; }

    public static List<Title> GetAvailableTitles()
    {
        var titles = new List<Title>();

        titles.Add(new Title(1, "Mr"));
        titles.Add(new Title(2, "Miss"));
        titles.Add(new Title(3, "Mrs"));

        return titles;
    }
}

MainWindowViewModel.cs

public class MainWindowViewModel : ViewModelBase
{
    private ObservableCollection<Person> contacts;
    private List<Title> titles;

    public MainWindowViewModel()
    {
        titles = Title.GetAvailableTitles();

        Contacts = new ObservableCollection<Person>();
        Contacts.Add(new Person() { FirstName = "Jane", LastName = "Smith", TitleId = 2 });
    }

    public List<Title> Titles
    {
        get { return titles; }
    }

    public ObservableCollection<Person> Contacts
    {
        get { return contacts; }
        set
        {
            if (contacts != value)
            {
                contacts = value;
                this.OnPropertyChanged("Contacts");
            }
        }
    }
}

ViewModelBase.cs

public class ViewModelBase : INotifyPropertyChanged
{
    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

解决方案

Here is a working code. The key point here was to use SelectedValueBinding instead of SelecteItemBinding.

<DataGridComboBoxColumn Header="Title" 
                        SelectedValueBinding="{Binding TitleId}"
                        SelectedValuePath="TitleId"
                        DisplayMemberPath="TitleText"
                        >
    <DataGridComboBoxColumn.ElementStyle>
        <Style TargetType="ComboBox">
            <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Titles}"/>
        </Style>
    </DataGridComboBoxColumn.ElementStyle>
    <DataGridComboBoxColumn.EditingElementStyle>
        <Style TargetType="ComboBox">
            <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Titles}"/>
        </Style>
    </DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>

这篇关于将WPF DataGridComboBoxColumn绑定到MVVM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆