c#wpf combobox将源绑定到一个集合,将item作为另一个集合的属性

时间:2018-03-26 11:49:25

标签: c# wpf combobox binding

我正在尝试将itemssource的{​​{1}}绑定到对象(combobox)集合的属性到另一个对象(Source1)的属性中MyCollection中的DataGridTemplateColumn

查看:

DataGrid

ViewModel(模型(包括视图类的其余部分)):

<Window x:Class="TestWPF.MainWindow"
        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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TestWPF"
        mc:Ignorable="d"
        Title="Test WPF" Height="350" Width="525">
    <Window.DataContext>
        <local:ViewModel></local:ViewModel>
    </Window.DataContext>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Label Content="Testing DATAGRIDTEMPLATECOLUMN with COMBOBOX" FontFamily="Verdana" FontSize="16" Grid.Column="0" Grid.Row="0"/>
        <DataGrid Grid.Column="0" Grid.Row="1" ItemsSource="{Binding MyCollection}" CanUserAddRows="True" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Name}" Header="Name of person"/>
                <DataGridTemplateColumn Header="Age of person" >
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Grid>
                                <ComboBox ItemsSource="{Binding Path=DataContext.Source1,
                                        RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window}}"
                                              SelectedValue="{Binding Age}" DisplayMemberPath="Number"/>
                            </Grid>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTextColumn Binding="{Binding Salary}" Header="Persons salary"/>
            </DataGrid.Columns>
        </DataGrid>
        <!-- Just for checking -->
        <DataGrid Grid.Column="0" Grid.Row="2" ItemsSource="{Binding MyCollection}" CanUserAddRows="True" AutoGenerateColumns="True"/>
    </Grid>
</Window>

最后是Source1类:

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;

namespace TestWPF
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        ViewModel vm;
        public MainWindow()
        {
            InitializeComponent();

        }


    }

    public class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

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

        private ObservableCollection<MyClass> _myCollection;

        private ObservableCollection<Source1> _source1;

        public ObservableCollection<Source1> Source1
        {
            get { return _source1; }
            set { _source1 = value; }
        }


        public ViewModel()
        {
            _source1 = new ObservableCollection<TestWPF.Source1>();
            _myCollection = new ObservableCollection<MyClass>();
            SetupSource();

        }

        private void SetupSource()
        {
            _source1.Add(new TestWPF.Source1(2));
            _source1.Add(new TestWPF.Source1(3));
            _source1.Add(new TestWPF.Source1(5));
            _source1.Add(new TestWPF.Source1(8));
        }

        public ObservableCollection<MyClass> MyCollection
        {
            get { return _myCollection; }
            set { _myCollection = value; NotifyPropertyChanged(nameof(MyCollection)); }
        }


    }
}

和MyClass:

namespace TestWPF
{
    public class Source1
    {
        public int Number { get; set; }

        public Source1(int n)
        {
            Number = n;
        }
    }
}

当我运行这个时,我得到错误和建议,为Source1创建转换器namespace TestWPF { public class MyClass { public string Name { get; set; } public int Age { get; set; } public double Salary { get; set; } public MyClass() { } public MyClass(string n, int a, double s) { Name = n; Age = a; Salary = s; } } } 。我认为System.Int32的{​​{1}}会将SelectedValue="{Binding Age}"的年龄与ComboBox联系起来。 有没有办法以这种方式连接两个不同类的两个属性,还是有必要创建一个转换器? 我想创建一个MyClass属性,它将使用Linq从Source1集合返回DisplayedMemberPath列表,并将其用作read-only Source1.Number,但我想知道这是否与使用转换器相比,这是不好的做法吗?

1 个答案:

答案 0 :(得分:1)

我认为您的问题是因为您没有在组合中设置所需的所有属性。

尝试

<ComboBox ItemsSource="{Binding Path=DataContext.Source1,
          RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window}}"
          SelectedValue="{Binding Age}"
          SelectedValuePath="Number" 
          DisplayMemberPath="Number"/>

Source1可能只有一个属性但组合框不是智能的,所以它试图将(Age)一个int设置为Source1的实例而不是int。