簡體   English   中英

從代碼中突出顯示 ListView 項 - WPF 數據綁定

[英]Highlight ListView Item From Code - WPF Data Binding

我訪問過的以前的來源(但沒有找到答案):

  1. 突出顯示 WPF 中的行
  2. 所選項目顏色
  3. 突出顯示 WPF 列表視圖中的項目
  4. 樣式觸發器
  5. Styles 用於造型

更密切相關但過於復雜/不完全是我需要的來源。

一般信息:

如標記,此代碼在c#中,使用WPF ,目標框架.NET Framework 4.5

注意:這是我第一次嘗試實現MVVM ,因此我將不勝感激有關我缺少的最佳實踐的評論(盡管這不是這個問題的主要主題)。

問題:

WPF 帶有ListViewButton ButtonListView中刪除項目。

ListView<String> (View) ---> RemoveStringFromList() (ViewModel)

以上工作。 我的問題是突出顯示

我希望能夠從 ListView 中刪除一個字符串,並在刪除后突出顯示不同的 Item

我最初的想法是,通過使用與ListViewSelectedItem屬性綁定的屬性 ( SelectedItemProperty ) - 突出顯示將是自動的。

但在實踐中, SelectedItem屬性綁定有效——因為我可以繼續按下Button並刪除根據SelectedItemProperty設置器中實現的邏輯成為SelectedItem的項目——但盡管它們是按代碼選擇的,但它們沒有突出顯示。

代碼:

主窗口.xaml

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="213.06">
    <Grid>
        <ListView ItemsSource="{Binding ItemsProperty}" SelectedItem="{Binding SelectedItemProperty}" HorizontalAlignment="Left" Height="214" Margin="35,74,0,0" VerticalAlignment="Top" Width="142">
            <ListView.View>
                <GridView>
                    <GridViewColumn/>
                </GridView>
            </ListView.View>
        </ListView>
        <Button Command="{Binding RemoveString}" Content="Remove From List!" HorizontalAlignment="Left" Margin="35,10,0,0" VerticalAlignment="Top" Width="142" Height="46"/>

    </Grid>
</Window>

主窗口.xaml.cs

using System.Windows;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        private readonly MainWindowViewModel _viewModel;

        public MainWindow()
        {
            InitializeComponent();
            _viewModel = new MainWindowViewModel();
            DataContext = _viewModel;
            Show();
        }
    }
}

MainWindowViewModel.cs

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;

namespace WpfApplication1
{
    public class MainWindowViewModel : INotifyPropertyChanged
    {
        private ObservableCollection<String> _list;
        private String _selectedItem;

        public MainWindowViewModel()
        {
            _list = new ObservableCollection<String> {"1", "2", "3", "4"};
            RemoveString = new RemoveStringCommand(this);
        }

        public ObservableCollection<String> ItemsProperty
        {
            get { return _list; }
        }

        public String SelectedItemProperty
        {
            get { return _selectedItem; }
            set
            {
                if (value != null)
                {
                    _selectedItem = value;
                }
                else
                {
                    if (_list.Count > 0)
                    {
                        _selectedItem = _list[0];
                    }
                }
            }
        }

        public ICommand RemoveString
        {
            get;
            private set;
        }

        public bool CanRemoveString
        {
            get { return _list.Count > 0; }
        }

        public void RemoveStringFromList()
        {
            if (SelectedItemProperty != null)
            {
                _list.Remove(SelectedItemProperty);
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged(String propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }


    }
}

RemoveStringCommand.cs

using System.Windows.Input;
using WpfApplication1;

namespace WpfApplication1
{
    class RemoveStringCommand : ICommand
    {
        private MainWindowViewModel _viewModel;

        public RemoveStringCommand(MainWindowViewModel viewModel)
        {
            _viewModel = viewModel;
        }

        public event System.EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public bool CanExecute(object parameter)
        {
            return _viewModel.CanRemoveString;
        }

        public void Execute(object parameter)
        {
            _viewModel.RemoveStringFromList();
        }
    }
}

應用圖片 - 首次點擊之前

在此處輸入圖像描述

應用程序圖片 - 單擊 1 次后(注意 - 沒有突出顯示!)

在此處輸入圖像描述

應用圖片 - 2 次點擊后(仍然沒有突出顯示...)

在此處輸入圖像描述

首先刪除一個錯誤

public MainWindow()
{
    InitializeComponent();
    _viewModel = new MainWindowViewModel();
    DataContext = _viewModel;
    // Show(); remove this, it's not needed
}

我用兩個可重用的輔助類做了一個例子。

1)第一個常見的 class 實現INotifyPropertyChanged 在每個 ViewModel class 中重復實現 INPC 可能會有所幫助。

public class NotifyPropertyChanged : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null)
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

[CallerMemberName]此處允許不在每個OnPropertyChanged()調用中包含屬性名稱。 編譯器會自動完成。

2) Class 便於命令使用。 (在這里抓到)

public class RelayCommand : ICommand
{
    private readonly Action<object> _execute;
    private readonly Func<object, bool> _canExecute;

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter) => _canExecute == null || _canExecute(parameter);
    public void Execute(object parameter) => _execute(parameter);
}

3)在以下示例中,我根據您的要求更改了屬性的名稱。 不要命名諸如SomethingProperty之類的屬性以避免與依賴屬性發生沖突,這種命名模式僅對 DP 有用。

標記:

<Grid>
    <ListView ItemsSource="{Binding ItemsList}" SelectedIndex="{Binding SelectedItemIndex}" HorizontalAlignment="Left" Height="214" Margin="35,74,0,0" VerticalAlignment="Top" Width="142">
        <ListView.View>
            <GridView>
                <GridViewColumn/>
            </GridView>
        </ListView.View>
    </ListView>
    <Button Command="{Binding RemoveItem}" Content="Remove From List!" HorizontalAlignment="Left" Margin="35,10,0,0" VerticalAlignment="Top" Width="142" Height="46"/>
</Grid>

4)視圖模型:

public class MainWindowViewModel : NotifyPropertyChanged
{
    private ObservableCollection<string> _itemsList;
    private int _selectedItemIndex;
    private ICommand _removeItem;

    public MainWindowViewModel()
    {
        // never interact with fields outside of the property 'set' clause
        // use property name instead of back-end field
        ItemsList = new ObservableCollection<string> { "1", "2", "3", "4" };
    }

    public ObservableCollection<string> ItemsList
    {
        get => _itemsList;
        set
        {
            _itemsList = value;
            OnPropertyChanged(); // Notify UI that property was changed

            //other ways doing the same call
            // OnPropertyChanged("ItemsList");
            // OnPropertyChanged(nameof(ItemsList));
        }
    }

    public int SelectedItemIndex
    {
        get => _selectedItemIndex;
        set
        {
            _selectedItemIndex = value;
            OnPropertyChanged();
        }
    }

    // command will be initialized in "lazy" mode, at a first call.
    public ICommand RemoveItem => _removeItem ?? (_removeItem = new RelayCommand(parameter =>
    {
        ItemsList.RemoveAt(SelectedItemIndex);
    }, 
    // SelectedItemIndex -1 means nothing is selected
    parameter => SelectedItemIndex >=0 && ItemsList.Count > 0));
}

作為獎勵,您可以以編程方式更改ListViewSelectedIndex ,只需將任何值設置為SelectedItemIndex

編輯:

抱歉,我忘記在刪除后保留選擇。 修改命令:

public ICommand RemoveItem => _removeItem ?? (_removeItem = new RelayCommand(parameter =>
{
    int index = SelectedItemIndex;
    ItemsList.RemoveAt(index);
    if (ItemsList.Count > 0)
        SelectedItemIndex = (index == ItemsList.Count) ? index - 1 : index;
}, parameter => SelectedItemIndex >= 0 && ItemsList.Count > 0));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM