#c# #wpf #mvvm #data-binding
#c# #wpf #mvvm #привязка данных
Вопрос:
Я пытаюсь установить содержимое для ListView из Properties .Настройки (StringCollection). Завершение установлено успешно, но если я удаляю элемент, ListView не обновляется. Если я закрою и открою SettingWindow, содержимое внутри ListView будет правильным. Это означает, что что-то не так в привязке данных, вероятно, не работает с PropertyChanged.
SettingWindow.xaml:
<Window x:Class="FilmDbApp.Views.SettingWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:p="clr-namespace:FilmDbApp.Properties"
xmlns:local="clr-namespace:FilmDbApp.Views"
mc:Ignorable="d"
Title="Setting" Height="500" Width="400" ResizeMode="NoResize" WindowStartupLocation="CenterOwner">
<DockPanel>
<TabControl>
<TabItem Header="Genre options">
<StackPanel>
<ListView ItemsSource="{Binding Source={x:Static p:Settings.Default}, Path=Genres, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding SelectedGenre}"" VerticalAlignment="Top"/>
<Button Command="{Binding DeleteGenreCommand}" CommandParameter="{Binding SelectedGenre}" Content="Delete"/>
</StackPanel>
</TabItem>
<TabItem Header="Autosave options"/>
</TabControl>
</DockPanel>
</Window>
SettingWindow.cs:
using System.Windows;
using FilmDbApp.ViewModels;
namespace FilmDbApp.Views
{
/// <summary>
/// Interaction logic for SettingWindow.xaml
/// </summary>
public partial class SettingWindow : Window
{
public SettingWindow()
{
InitializeComponent();
DataContext = new SettingWindowViewModel();
}
}
}
Настройка windowviewmodel.cs:
using System.ComponentModel;
using System.Runtime.CompilerServices;
using FilmDbApp.Views;
using FilmDbApp.Models;
using FilmDbApp.Utils;
namespace FilmDbApp.ViewModels
{
class SettingWindowViewModel : INotifyPropertyChanged
{
private string selectedGenre;
public string SelectedGenre
{
get { return selectedGenre; }
set
{
selectedGenre = value;
OnPropertyChanged("SelectedGenre");
}
}
public SettingWindowViewModel()
{
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string prop = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
// Delete genre
private RelayCommand deleteGenreCommand;
public RelayCommand DeleteGenreCommand
{
get
{
return deleteGenreCommand ??
(deleteGenreCommand = new RelayCommand(obj =>
{
string genre = obj as string;
Properties.Settings.Default.Genres.Remove(genre);
Properties.Settings.Default.Save();
OnPropertyChanged("Genres");
}, (obj) => Properties.Settings.Default.Genres.Count > 0 amp;amp; obj != null));
}
}
}
}
Комментарии:
1. Если вы имели в виду, что удаляете строку списка, то вам нужно иметь ObservableCollection, который запускает события CollectionChanged, а не PropertyChanged
2. вы также можете использовать функцию обновления из CollectionViewSource?
3. Нет, вы не можете обновлять привязки подобным образом. Вы указываете другой источник. Простой обходной путь — создать свойство только для получения, в
SettingWindowViewModel
котором будет перенаправлятьсяProperties.Settings.Genres
и использовать его в привязках. Затем вы можете вызвать уведомление об этом в command.4. Как примечание, настройка
UpdateSourceTrigger=PropertyChanged
привязки ItemsSource бессмысленна. Это влияет только на привязки TwoWay или OneWayToSource.5. @Sinatr, я должен создать метод внутри
SettingWindowViewModel
, который будет: 1) Получать элементы изProperties.Settings.Genres
toObservableCollection
2) Подключать ListViewObservableCollection
и что-то делать 3) КонвертироватьObservableCollection
обратно вProperties.Settings.Genres
?
Ответ №1:
Вместо привязки к какому-либо другому свойству в каком-либо другом источнике вы можете использовать возможности ViewModel, которая используется для работы между view и models .
Добавьте следующее свойство в ViewModel
class SettingWindowViewModel : INotifyPropertyChanged
{
public List<Genre> Genres => Properties.Settings.Default.Genres;
...
}
и привязать к нему
<ListView ItemsSource="{Binding Genres}"
SelectedItem="{Binding SelectedGenre}"... />
Теперь внутри различных команд вы должны иметь возможность указывать привязки для обновления
OnPropertyChanged(nameof(Genres));