简体   繁体   English

如何使用仅使用XAML数据绑定的DataGrid获取行选择

[英]How to get row selection working with DataGrid using XAML only databinding

I have the following DataGrid definition 我有以下DataGrid定义

 <DataGrid
    VirtualizingPanel.VirtualizationMode="Recycling"
    CanUserAddRows="False"
    CanUserDeleteRows="False"
    SelectionMode="Single"
    ItemsSource="{Binding 
        ToolPath.ToolPath, 
        Mode=OneWay,
        Converter={StaticResource indexedConverter}}" 
    AutoGenerateColumns="False" 
    SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}">

I'm using MVVM and have a view model with a SelectedIndex property implementing INPC. 我使用的是MVVM,并具有一个带有实现INPC的SelectedIndex属性的视图模型。 I've used snoop to verify that the SelectedIndex on the DataGrid changes when it does in the view model. 我已经使用snoop来验证DataGrid上的SelectedIndex在视图模型中更改时是否发生了更改。 However the row of the grid is not selected or highlighted when I do so. 但是,当我这样做时,并未选择或突出显示网格的行。

在此处输入图片说明

As you can see the row is not highlighted but I think I can detect that the little 3 pixel wide widget to the left of the row is a darker blue. 如您所见,该行未突出显示,但我认为我可以检测到该行左侧的3像素宽的小部件是深蓝色。

Is there a XAML only way via databinding ( without writing code behind ) to get row selection working? 是否XAML only via databindingwithout writing code behind )才能使行选择正常工作的XAML only方式?

Can't seem to figure out a way from XAML. 似乎无法从XAML中找出一种方法。 With much hacking and reading posts the best I can come up with is. 有了很多骇客和阅读文章,我能想到的最好的就是。

<DataGrid
    x:Name="ToolPathGridView"
    VirtualizingPanel.VirtualizationMode="Recycling"
    CanUserAddRows="False"
    SelectionUnit="FullRow"
    CanUserDeleteRows="False"
    SelectionMode="Single"
    Loaded="ToolPathGridView_Loaded"
    ItemsSource="{Binding 
        ToolPath.ToolPath, 
        Mode=OneWay,
        Converter={StaticResource indexedConverter}}" 
    AutoGenerateColumns="False" 
    SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}">

and

private void ToolPathGridView_Loaded( object sender, RoutedEventArgs e )
{
    ToolPathGridView.ItemContainerGenerator.StatusChanged += new EventHandler(ItemContainerGenerator_StatusChanged);
}
 void ItemContainerGenerator_StatusChanged( object sender, EventArgs e )
{
    if ( ToolPathGridView.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated )
    {
        int i = 0;
        if ( ViewModel!=null )
        {
            i = ViewModel.SelectedIndex;
        }
        ToolPathGridView.SelectedIndex = 0;
        DataGridRow r = ToolPathGridView.ItemContainerGenerator.ContainerFromIndex(0) as DataGridRow;
        if ( r != null )
        {
            r.IsSelected = false;
            r.IsSelected = true;
        }
    }
}

so what is happening here. 所以这里发生了什么。 The trick seems to be that you have to wait till the datagrid has built it's internal container model. 诀窍似乎是您必须等到datagrid建立其内部容器模型为止。 When that is done you can pick off a row and mark it as selected. 完成后,您可以选择一行并将其标记为选中状态。 If you try to do this too early there are no rows. 如果尝试过早进行此操作,则不会有任何行。

This really should be a property of the grid itself. 这确实应该是网格本身的属性。

Working example using MVVM light from NuGet . 使用来自NuGet的 MVVM光源的工作示例。

You can write the index in the lower textbox to see it changing on the DataGrid. 您可以在下部文本框中编写索引,以查看它在DataGrid上的变化。

MainWindow.xaml MainWindow.xaml

<Window
    x:Class="Test_DataGridSelectedIndexItem.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:testDataGridSelectedIndexItem="clr-namespace:Test_DataGridSelectedIndexItem"
    Title="MainWindow"
    Height="350"
    Width="525"
    >
    <Window.DataContext>
        <testDataGridSelectedIndexItem:MainViewModel />
    </Window.DataContext>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height=".9*"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <DataGrid
            Grid.Row="0"
            ItemsSource="{Binding Items}"
            SelectedItem="{Binding Selected, Mode=TwoWay}"
            SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}"
            />

        <TextBlock
            Grid.Row="1"
            Text="{Binding Selected}"
            />

        <TextBlock
            Grid.Row="2"
            Text="{Binding SelectedIndex}"
            />

        <TextBox
            Grid.Row="3"
            Text="{Binding SelectedIndex, Mode=TwoWay}"
            />
    </Grid>
</Window>

MainViewModel.cs MainViewModel.cs

using System.Collections.ObjectModel;
using GalaSoft.MvvmLight;

namespace Test_DataGridSelectedIndexItem
{
    public class MainViewModel : ViewModelBase
    {
        private ItemViewMode selected;
        private int selectedIndex;

        public MainViewModel()
        {
            this.Items = new ObservableCollection<ItemViewMode>()
                         {
                             new ItemViewMode("Item1"),
                             new ItemViewMode("Item2"),
                             new ItemViewMode("Item3"),
                         };
        }

        public ObservableCollection<ItemViewMode> Items { get; private set; }

        public ItemViewMode Selected
        {
            get
            {
                return this.selected;
            }
            set
            {
                this.selected = value;
                this.RaisePropertyChanged(() => this.Selected);
            }
        }

        public int SelectedIndex
        {
            get
            {
                return this.selectedIndex;
            }
            set
            {
                this.selectedIndex = value;
                this.RaisePropertyChanged(() => this.SelectedIndex);
            }
        }
    }
}

ItemViewModel.cs ItemViewModel.cs

using GalaSoft.MvvmLight;

namespace Test_DataGridSelectedIndexItem
{
    public class ItemViewModel : ViewModelBase
    {
        private string text;

        public ItemViewModel() : this(string.Empty)
        {
        }

        public ItemViewModel(string text)
        {
            this.text = text;
        }

        public string Text
        {
            get
            {
                return this.text;
            }
            set
            {
                this.text = value;
                this.RaisePropertyChanged(() => this.Text);
            }
        }

        public override string ToString()
        {
            return this.text;
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM