【问题标题】:How to get the SelectedItem of several datagrids?如何获取多个datagrids的SelectedItem?
【发布时间】:2017-03-01 15:15:41
【问题描述】:

Foreach treeview-item 我有一个自己的数据网格。 Treeview-items 和 datagrids 通过绑定填充。

在文本框上,我绑定了数据网格的选定项。但是这些文本框上的绑定仅适用于第一个数据网格。其他所有数据网格都不会将选定项传输到文本框:

这是带有数据网格的树视图:

            <TreeView ItemsSource="{Binding Path=PlaceList}">
                <TreeView.ItemTemplate>
                    <DataTemplate>
                        <TreeViewItem Header="{Binding Path=Name}">
                            <DataGrid ItemsSource="{Binding MachinesInPlace, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                      SelectionUnit="FullRow"
                                      SelectedItem="{Binding SelectedMachine, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                      AutoGenerateColumns="True"
                                      IsSynchronizedWithCurrentItem="True"
                                      SelectionMode="Single">
                            </DataGrid>
                        </TreeViewItem>
                    </DataTemplate>
                </TreeView.ItemTemplate>
            </TreeView>

这是文本框:

<TextBox Text="{Binding PlaceList/SelectedMachine.Name, ValidatesOnDataErrors=True}" />

我正在使用 MvvmLight。我的 ViewModel 拥有 PlaceList:

    public ObservableCollection<PlaceModel> PlaceList { get; set; } = new ObservableCollection<PlaceModel>();

    public ObjectInspectorViewModel()
    {
        PlaceList = PlaceModel.GetPlaces(BaseResourcePaths.PlacesCsv);
    }

那是我的地方模型:

public class PlaceModel
{
    public int Id { get; set; }
    public string Name { get; set; } = "_CurrentObjectName";
    public string Length { get; set; }
    public string Width { get; set; }
    public string Height { get; set; }
    public ObservableCollection<MachineModel> MachinesInPlace { get; set; }
    public MachineModel SelectedMachine { get; set; }

    public static ObservableCollection<PlaceModel> GetPlaces(string filepath)
    {
        [...]
    }
}

我尝试了一些东西,但最后我不知道如何修复这个错误。有什么问题?我的建议是放置模型内的属性“SelectedMachine”...

这是一个示例项目(带有 Sebastian Richter 的附加解决方案)。它显示了问题:https://www.file-upload.net/download-12370581/DatagridTreeViewError.zip.html

【问题讨论】:

  • 你不需要树视图上的 SelectedItem,然后根据它绑定到文本框吗?否则,绑定只是抓取第一个实例,而不是在进行树视图选择时更新。
  • 谢谢你的回复。我尝试了您的解决方案,但没有奏效。我必须使用 stackoverflow.com/a/3535089 上的 SelectedItem 属性扩展树视图控件。我最终得到了以下 XAML:pastebin.com/VVgBtCqR 问题是树视图包含一个充满位置的列表,并且每个位置都有一个不同的(数据网格)机器列表。因此,在 treeview-select 上,我可以获得选择了哪个位置列表,但我无法获得选择了这些位置列表中的哪台机器。还是我错了?

标签: wpf binding datagrid mvvm-light


【解决方案1】:

我很确定你忘记在你的班级 PlaceModel 中实现 INotifyPropertyChanged。问题是在您更改选择后,属性Placemodel.SelectedMachine 将被更新,但不会触发任何事件来填充视图中的此更改。

因为您使用 MVVM Light,您可以从已经实现此接口的ObservableObject 派生。 因此,将您的 PlaceModel 更改为以下代码:

public class PlaceModel : ObservableObject
{
    private MachineModel _selectedMachine;
    public int Id { get; set; }
    public string Name { get; set; } = "_CurrentObjectName";
    public string Length { get; set; }
    public string Width { get; set; }
    public string Height { get; set; }
    public ObservableCollection<MachineModel> MachinesInPlace { get; set; }

    public MachineModel SelectedMachine
    {
        get
        {
            return _selectedMachine;
        }

        set
        {
            // raises Event PropertyChanged after setting value
            Set(ref _selectedMachine, value);
        }
    }

    public static ObservableCollection<PlaceModel> GetPlaces(string filepath)
    {
    [...]
}

编辑:

我猜绑定不知道要从您的ObservableCollection(多对一关系)绑定到哪个元素,因为您将它设置为TextBox 中的引用。

所以尝试从 Model 中移除 SelectedMachine 属性并将其添加回 ViewModel:

class ViewModel : ViewModelBase
{
     ...
     private MachineModel _selectedMachine;
     public MachineModel SelectedMachine
     {
        get
        {
            return _selectedMachine;
        }
        set
        {
        // raises Event PropertyChanged after setting value
        Set(ref _selectedMachine, value);
        }
    }
    ...
}

还将您的 XAML 更改为以下代码(我使用了您的示例项目):

<Grid x:Name="LayoutRoot">
    <Grid.RowDefinitions>
        <RowDefinition Height="2*"></RowDefinition>
        <RowDefinition></RowDefinition>
    </Grid.RowDefinitions>

    <!-- Row #1 -->
    <Grid>
        <!-- TreeView und DataGrids-->
        <TreeView ItemsSource="{Binding Path=PlaceList}">
            <TreeView.ItemTemplate>
                <DataTemplate>
                    <TreeViewItem Header="{Binding Path=Name}">
                        <DataGrid ItemsSource="{Binding MachinesInPlace, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                  SelectedItem="{Binding DataContext.SelectedMachine, RelativeSource={RelativeSource AncestorType=Window},Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                    </TreeViewItem>
                </DataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    </Grid>

    <!-- Row #2 -->
    <Grid Grid.Row="1">
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition Width="2*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>

        <Label Grid.Row="0"
               Content="ID" />
        <!-- Textboxen aktualisieren nur bei Auswahl der ersten Datagrid -->
        <TextBox Grid.Column="2"
                 Grid.Row="0"
                 Text="{Binding SelectedMachine.Id, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        <Label Grid.Row="1"
               Content="Name" />
        <TextBox Grid.Column="2"
                 Grid.Row="1"
                 Text="{Binding SelectedMachine.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
    </Grid>
</Grid>

关键是为SelectedItem 设置正确的DataContext。为此,我使用了以下 XAML 代码:

<DataGrid ItemsSource="{Binding MachinesInPlace, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                  SelectedItem="{Binding DataContext.SelectedMachine, RelativeSource={RelativeSource AncestorType=Window},Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

这样,您的示例项目会正确更新文本框。

【讨论】:

  • 感谢您的帮助。事实上,我忘记了INotifyPropertyChanged-interface/ObservableObject。我将这个想法添加到我的代码中,但它并没有解决问题。在我的问题中,我添加了一个更准确地显示问题的项目示例。我认为SelectedMachine 必须在PlaceModel 之外。但是如果我将属性PlaceListSelectedMachine 放入我的视图模型中,我将无法在我的xaml-datagrid 中访问SelectedMachine,因为我在上面的树视图中设置了PlaceListpastebin.com/20HwpPga
  • 非常感谢您的努力!有问题的视觉工作室没有在绑定窗口上向我显示属性DataContext.SelectedMachine,所以我需要手动设置它。见this picture。如果没有您的帮助,我永远不会发现这一点,非常感谢!
  • 没问题。我总是从这些问题中学到新的东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-18
  • 1970-01-01
  • 2015-05-15
  • 1970-01-01
  • 1970-01-01
  • 2012-12-09
  • 1970-01-01
相关资源
最近更新 更多