Выбранный элемент в ListView исчезает

#c# #wpf #listview

#c# #wpf #listview

Вопрос:

Я создал минималистичный образец, используя ListView с тремя элементами в нем и ContentControl рядом с ним, который отображает выбранный элемент ListViewItem. Что меня озадачивает, так это то, что когда я выбираю элемент, он отображается правильно в ContentControl, но становится таким маленьким в ListView, как если бы он исчезал. Кто-нибудь может объяснить мне, что здесь происходит?

Главное окно с ListView и ContentControl в сетке. ContentControl.Содержимое привязывается к выбранному элементу ListView.

 <Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <ListView ItemsSource="{Binding ListViewItems}" SelectedItem="{Binding SelectedListViewItem}"/>
        <ContentControl Grid.Column="1" Content="{Binding SelectedListViewItem}"/>
    </Grid>
</Window>
  

В MainWindow для DataContext установлено значение MainWindowViewModel

 using System.Windows;
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainWindowViewModel();
    }
}
  

MainWindowViewModel реализует INotifyPropertyChanged и содержит элементы ListViewItems, а также SelectedListViewItem.

 using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Controls;

public class MainWindowViewModel : INotifyPropertyChanged
{
    public MainWindowViewModel()
    {
        ListViewItems = new ObservableCollection<Control>()
        {
            new TextBox(){ Text = "TB1", IsReadOnly = true },
            new TextBox(){ Text = "TB2", IsReadOnly = true },
            new TextBox(){ Text = "TB3", IsReadOnly = true },
        };
    }

    private ObservableCollection<Control> _listViewItems;
    private Control _selectedListViewItem;

    public ObservableCollection<Control> ListViewItems
    {
        get
        {
            return _listViewItems;
        }
        set
        {
            if (SetProperty(ref _listViewItems, value))
            {
            }
        }
    }

    public Control SelectedListViewItem
    {
        get
        {
            return _selectedListViewItem;
        }
        set
        {
            if (SetProperty(ref _selectedListViewItem, value))
            {
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

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

    protected virtual bool SetProperty<T>(ref T backingField, T newValue, [CallerMemberName] string propertyName = null)
    {
        var ret = false;
        if (!EqualityComparer<T>.Default.Equals(backingField, newValue))
        {
            backingField = newValue;
            OnPropertyChanged(propertyName);
            ret = true;
        }

        return ret;
    }
}
  

Я знаю, что ViewModel не должен содержать никаких ссылок на какое-либо представление. Однако из минимальной выборки это было необходимо. Вопрос для меня в том, почему элементы ListViewItems «исчезают».

Эффект нажатия кнопки

Я нажал на первый элемент ListViewItem, TB1. Он отображается в contentcontrol справа, но ListView теперь выглядит странно. Я могу повторить это и для других элементов ListViewItems.

введите описание изображения здесь

Это происходит после нажатия также на TB2, а затем, наконец, на TB3

Ответ №1:

Ваша проблема в том, что элемент управления может появиться только один раз в пользовательском интерфейсе.

Вы создаете элементы управления в коде.

Когда вы выбираете один, он берется с того места, где вы его выбрали, и перемещается туда, где вы его привязали.

Не создавайте элементы управления в коде.

Используйте mvvm.

Создайте данные (viewmodels ) и привяжите к пользовательскому интерфейсу.

Datatemplate эти данные в элементы управления.

Комментарии:

1. Спасибо, это очень хорошо объясняет то, что я наблюдал. Я не знал об этом движущемся поведении.