c#wpf combobox将source绑定到一个collection,item作为另一个collection的属性

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c#wpf combobox将source绑定到一个collection,item作为另一个collection的属性相关的知识,希望对你有一定的参考价值。

我试图将itemssourcecombobox绑定到对象(Source1)集合的属性到MyCollectionDataGridTemplateColumn中的另一个对象(DataGrid)的属性:

视图:

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

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

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)); }
        }


    }
}

最后是Source1类:

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

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

和MyClass:

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;
        }
    }
}

当我运行这个时,我得到错误和建议为Source1创建转换器到System.Int32。我认为SelectedValue="{Binding Age}"ComboBox会将MyClass的年龄与DisplayedMemberPath联系起来。有没有办法以这种方式连接两个不同类的两个属性,还是有必要创建一个转换器?我想创建一个read-only属性,它将使用Linq从Source1集合中返回Source1.Number列表,并将其用作Itemssourcecombobox,但我想知道与使用转换器相比这是不是很糟糕吗?

答案

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

尝试

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

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

以上是关于c#wpf combobox将source绑定到一个collection,item作为另一个collection的属性的主要内容,如果未能解决你的问题,请参考以下文章

C# WPF ComboBox - 排除绑定数据的最后一行(或空格)(从 Microsoft Access 绑定)

在wpf中怎么绑定comboBox的值

WPF 将集合绑定到 ComboBox 并选择一个项目

将 wpf:ComboBox 绑定到 XAML 中的静态类

WPF MVVM 将 ComboBox 绑定到 Datagrid 选定项

WPF将comboBox绑定到List