【问题标题】:Extracting Data from DataGrid into Binded Combobox将 DataGrid 中的数据提取到绑定组合框中
【发布时间】:2016-10-13 13:34:34
【问题描述】:

我要做的是将字符串从我的 DataGrid 中的特定列中取出,并在 Combobox.Text 属性中显示该字符串。我正在使用此代码:

var dataString = ((DataRowView)dgvMain.SelectedItem).Row["Column"].ToString();

我已经为此设置了一个断点以查看它在拉什么,它是作为项目包含在 Combobox 中的正确字符串,但是每当我尝试通过 Combobox.Text 设置它时,Combobox 都是空的。但是,我已将我的 Combobox 设置为 isEditable = True 和 ReadOnly = True 并且此方法有效,但是由于 Combobox 已绑定到我的 DataTable,因此在集合中选择一个项目将显示 System.Data.DataRowView。我也会将 XAML 添加到我的 Combobox 中:

<ComboBox x:Name="cboAlarmType" HorizontalAlignment="Left" Margin="138,256,0,0" VerticalAlignment="Top" Width="320" TabIndex="5"
              BorderBrush="Black" Background="White" ItemsSource="{Binding}" DisplayMemberPath="AlarmName" SelectedValuePath="AlarmName" 
              SelectedValue="{Binding Row.Column, ElementName=dgvMain}"/>

此方法适用于文本框和复选框,但似乎还没有为组合框解决。任何指导将不胜感激! :)

【问题讨论】:

  • 如何填充 DataGrid?在 WPF 中,你不需要做这样丑陋的事情。只需转到您用于填充 DataGrid 的项目。此外,DataTemplate 中的多重绑定看起来像是猜测;您似乎没有做任何多重绑定将用于的事情。你用什么填充组合框?
  • 我正在通过 DataTable 填充 DataGrid。 DataTable 中的数据来自我的 SQLite 数据库中的 Select 语句。
  • &lt;DataTemplate&gt;&lt;TextBlock Text="{Binding Column}" /&gt;&lt;/DataTemplate&gt; 应该和你在那里的一样。
  • 我猜我将 Multibinding StringFormat 留在其中的原因是因为我一次合并了 2 列。你说得对,只需要一列。
  • 哦,所以DataRowView 是数据表中的一行,抱歉(derp)。组合框是否填充?我想你想要的可能是&lt;ComboBox DisplayMemberPath="Column" SelectedValuePath="Column" SelectedValue="{Binding Row.Column, ElementName=dgvMain}" ... /&gt;

标签: c# wpf data-binding combobox


【解决方案1】:

在我看来,ComboBoxDataContext 必须是您用来填充DataGridDataTable,因为ItemsSource="{Binding}"。我将假设DataGrid 也是DataContext,并且您的目标是让ComboBox 选择反映DataGrid 中的选定行。

<DataGrid
    x:Name="dgvMain"
    ItemsSource="{Binding}"
    />
<ComboBox
    ItemsSource="{Binding}"
    DisplayMemberPath="Column"
    SelectedValuePath="Column"
    SelectedValue="{Binding SelectedItem.Row[Column], ElementName=dgvMain}"
    />

如果您希望选择双向更改 -- 所以更改ComboBox 选择会更改DataGrid 选择 -- 这很简单:

<DataGrid
    x:Name="dgvMain"
    ItemsSource="{Binding}"
    SelectedValuePath="Column"
    SelectedValue="{Binding SelectedValue, ElementName=ColumnComboBox}"
    />
<ComboBox
    x:Name="ColumnComboBox"
    ItemsSource="{Binding}"
    DisplayMemberPath="Column"
    SelectedValuePath="Column"
    SelectedValue="{Binding SelectedItem.Row[Column], ElementName=dgvMain}"
    />

这是一种更简洁的方式来完成整个操作: 首先,用 C# 编写一个视图模型类。

public class ViewModelbase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class MyViewModel : ViewModelbase
{
    public MyViewModel()
    {
        //  I populated my DataTable with "Row 1", "Row 2", etc.
        //  Naturally you'd use a value from your own data. 
        SelectedColumnValue = "Row 2";
    }

    #region SelectedColumnValue Property
    private String _selectedColumnValue = default(String);
    public String SelectedColumnValue
    {
        get { return _selectedColumnValue; }
        set
        {
            if (value != _selectedColumnValue)
            {
                _selectedColumnValue = value;
                OnPropertyChanged();
            }
        }
    }
    #endregion SelectedColumnValue Property

    public DataTable Data { get; protected set; }
}

然后使用SelectedColumnValue 属性来跟踪两个控件的选定“列”值。默认情况下,两个控件的SelectedValue 属性上的绑定将是双向的,因为框架的东西使它成为这种方式(如何解释?)。因此,如果您以编程方式更改SelectedColumnValue,控件将更新,如果用户更改网格选择,viewmodel 属性将更新,进而更新ComboBox - 反之亦然。

<DataGrid
    ItemsSource="{Binding Data}"
    SelectedValuePath="Column"
    SelectedValue="{Binding SelectedColumnValue}"
    />
<ComboBox
    ItemsSource="{Binding Data}"
    DisplayMemberPath="Column"
    SelectedValuePath="Column"
    SelectedValue="{Binding SelectedColumnValue}"
    />
<ComboBox
    ItemsSource="{Binding Data}"
    DisplayMemberPath="ShoeSize"
    SelectedValuePath="Column"
    SelectedValue="{Binding SelectedColumnValue}"
    />

另一个问题是DisplayMemberPathSelectedValuePath 不必相同。假设我们在Data 中有一个“ShoeSize”列,我们希望将这些值显示在另一个 ComboBox 中。所以我们可以这样做。我们仍然使用Column 作为Data 中行的唯一标识符,但我们可以告诉ComboBox 显示其他列。

【讨论】:

  • 感谢所有帮助!将所有 XAML 属性保持为每行一个是一种好习惯,还是只是偏好?
  • @RockGuitarist1 如果一个元素有不止一个或两个属性,我发现它的可读性要高得多,尤其是在 StackOverflow 上,格式让你对代码的了解如此狭隘。水平滚动对读者来说很困难。
  • 那么可能是个好主意。我有 8 个组合框可以执行此操作,因此我必须寻找一种在 DataGrid 的 XAML 中拥有多个 SelectedValuePaths 和 SelectedValues 的方法。
  • @RockGuitarist1 你不能。它只有一个。你可以做的是有多个组合,它们都有一个SelectedValuePath="Column", but DisplayMemberPath`,它是DataTable中的不同列。
  • @RockGuitarist1 将其添加到答案中。
猜你喜欢
  • 2022-10-07
  • 1970-01-01
  • 2015-12-17
  • 1970-01-01
  • 2013-01-28
  • 1970-01-01
  • 2018-01-17
  • 1970-01-01
  • 2017-01-29
相关资源
最近更新 更多