WPF DataGrid SelectedItem - PullRequest
       3

WPF DataGrid SelectedItem

5 голосов
/ 02 февраля 2012

У меня есть DataGrid, к которому пользователь может добавлять элементы, вводя данные в последнюю строку. У меня также есть кнопка, которая удаляет текущий выбранный элемент. Но когда выбрана последняя (пустая, для добавления новых элементов) строка, то, что было последним выбранным элементом, остается в SelectedItem. Поэтому, если я открою окно, выделю последнюю строку и нажму кнопку удаления, она удалит первую строку, так как она выбрана по умолчанию, и выбор последней строки не изменил SelectedItem. Есть ли хороший способ справиться с этим?

уточнить: SelectedItem = "{Binding X}"

X в ViewModel не изменяется при выборе последней строки (установщик вообще не вызывается). Я не уверен, изменяется ли само свойство SelectedItem, но я бы предположил, что это не так.

Существует также исключение, когда я выбираю последнюю строку (красная граница), но когда я снова щелкаю по ней, чтобы начать ввод данных, красная рамка не работает. Не уверен, что эти двое связаны.

Ответы [ 3 ]

11 голосов
/ 02 февраля 2012

Запустите следующий пример, и вы поймете, почему он не работает.

XAML:

<Window x:Class="DataGridTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <DockPanel>
        <TextBlock DockPanel.Dock="Bottom" Text="{Binding SelectedItem, ElementName=dataGrid}"/>
        <TextBlock DockPanel.Dock="Bottom" Text="{Binding SelectedItem}"/>
        <DataGrid x:Name="dataGrid" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" CanUserAddRows="True" CanUserDeleteRows="True" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="First Name" Binding="{Binding FirstName}"/>
                <DataGridTextColumn Header="Last Name" Binding="{Binding FirstName}"/>
            </DataGrid.Columns>
        </DataGrid>
    </DockPanel>
</Window>

Кодовый код:

namespace DataGridTest
{
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Windows;

    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private readonly ICollection<Person> items;
        private Person selectedItem;

        public MainWindow()
        {
            InitializeComponent();

            this.items = new ObservableCollection<Person>();
            this.items.Add(new Person
                {
                    FirstName = "Kent",
                    LastName = "Boogaart"
                });
            this.items.Add(new Person
            {
                FirstName = "Tempany",
                LastName = "Boogaart"
            });

            this.DataContext = this;
        }

        public ICollection<Person> Items
        {
            get { return this.items; }
        }

        public Person SelectedItem
        {
            get { return this.selectedItem; }
            set
            {
                this.selectedItem = value;
                this.OnPropertyChanged("SelectedItem");
            }
        }

        private void OnPropertyChanged(string propertyName)
        {
            var handler = this.PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

    public class Person
    {
        public string FirstName
        {
            get;
            set;
        }

        public string LastName
        {
            get;
            set;
        }

        public override string ToString()
        {
            return FirstName + " " + LastName;
        }
    }
}

КакВы можете видеть, что при запуске выбор «новой» строки приводит к тому, что в качестве выбранного элемента в DataGrid устанавливается значение часового.Однако WPF не может преобразовать этот элемент стража в Person, поэтому привязка SelectedItem не удается преобразовать.

Чтобы это исправить, можно добавить преобразователь в привязку, который обнаружит страж и возвращаетnull при обнаружении.Вот конвертер, который делает это:

namespace DataGridTest
{
    using System;
    using System.Windows.Data;

    public sealed class SentinelConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value != null && string.Equals("{NewItemPlaceholder}", value.ToString(), StringComparison.Ordinal))
            {
                return null;
            }

            return value;
        }
    }
}

Как видите, крайне нежелательно проверять значение ToString() часового, потому что это внутренний тип.В качестве альтернативы (или дополнительно) вы можете проверить, что GetType().Name равно NamedObject.

0 голосов
/ 02 февраля 2012

Звучит так, будто вы забыли установить режим привязки, и по умолчанию установлено значение OneWay.Это означает, что любые изменения, сделанные в вашем представлении, не будут распространяться на вашу модель представления.

И всегда следите за тем, чтобы у вас был правильный текст данных.

Надеюсь, это поможет.

0 голосов
/ 02 февраля 2012

Сложно сказать без кода, но я бы посмотрел на следующее.

Убедитесь, что всякий раз, когда элемент удаляется, а также является выбранным элементом, установите для выбранного элемента, привязанного к свойству в ViewModel, значение null.Вам нужно убедиться, что ваш SelectedItem, привязанный к свойству, не привязан к одной стороне.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...