Пользовательский интерфейс не обновляется при изменении выбранного элемента - PullRequest
0 голосов
/ 15 ноября 2018

У меня есть ListBox, чей ItemSource связан с коллекцией PointStyleModel объектов, которая содержится в моем PointStylesViewModel. Класс PointStyleModel имеет три свойства: Размер, Имя и Цвет (Цвет имеет тип GeoColor - сторонний объект библиотеки).

A TextBox связан со свойством Name. Набор инструментов xceed IntegerUpDown привязан к размеру. Инструментарий xceed ColorPicker привязан к Color.

В настоящее время, когда пользователь выбирает новый элемент в списке, три элемента управления обновляются должным образом. Но если пользователь должен изменить значение IntegerUpDown или ColorPicker в пользовательском интерфейсе, а затем выбрать другой элемент в списке, пользовательский интерфейс не отобразит правильное значение. Я не хочу, чтобы свойства обновлялись только потому, что пользователь изменяет значение в пользовательском интерфейсе. TextBox, связанный с Name, работает нормально. Я пробовал различные режимы привязки и обновления источника, но безуспешно.

Вот мой класс модели:

public class PointStyleModel
{
    public int Size
    {
        get;
        set;
    }

    public string Name
    {
        get;
        set;
    }

    public GeoColor Color
    {
        get;
        set;
    }
}

Вот моя модель представления:

public class PointStylesViewModel : ViewModelBase //using Fody's PropertyChangedInterface in the base class
{
    public ObservableCollection<PointStyleModel> PointStyles { get; set; } //the listbox is bound to this

    public PointStyleModel SelectedPointStyle { get; set; } //bound to the listboxe's selected item

    public string PointStyleName { get { return SelectedPointStyle.Name; } }

    public Color PointStyleColor
    {
        get
        {
            return Color.FromArgb(SelectedPointStyle.Color.AlphaComponent, SelectedPointStyle.Color.RedComponent, SelectedPointStyle.Color.GreenComponent, SelectedPointStyle.Color.BlueComponent); //Need to convert GeoColor to Color
        }
    }

    public int PointStyleSize { get { return SelectedPointStyle.Size; } }

    public PointStylesViewModel()
    {
        PointStyles = new ObservableCollection<PointStyleModel>();
        AddDefaultPointStyles(); //add some default styles

        SelectedPointStyle = PointStyles.First(); //select the first item in the list when starting up
    }
}

Вот соответствующие разделы моего взгляда:

<TabItem DataContext="{Binding Path=PointStylesViewModel, Source={StaticResource ViewModelLocator}}">
    <Grid>
        <ListBox ItemsSource="{Binding PointStyles}" SelectedItem="{Binding SelectedPointStyle}" DisplayMemberPath="Name"/>
        <TextBox Text="{Binding PointStyleName, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
        <GroupBox Header="Paint">
            <Grid>
                <xctk:ColorPicker SelectedColor="{Binding Path=PointStyleColor, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" DisplayColorAndName="False" DisplayColorTooltip="True"/>
                <xctk:IntegerUpDown Value="{Binding PointStyleSize, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" Maximum="20" Minimum="0" />
            </Grid>
        </GroupBox>
    </Grid>
</TabItem>

Вот пример проблемы:

Сначала я выбираю элемент в списке. Все заполнено правильно. enter image description here

Теперь я изменю размер цвета только на интерфейсе: enter image description here

А потом я выберу другой элемент из списка: enter image description here

На первом рисунке я выбираю RedSquare6, и он заполняет ColorPicker свойством PointStyleColor в моей виртуальной машине. Он получает это значение из свойства Color в SelectedPointStyle. Это отлично работает.

На втором изображении я выбираю новый цвет из элемента управления ColorPicker, в данном случае розовый. Это не должно изменить любое свойство. Я просто меняю цвет элемента управления. Свойство Color в RedSquare6 по-прежнему должно быть красным.

На третьем изображении я выбираю GreenSquare6. Элемент управления ColorPicker должен теперь отображать зеленый, но он остается розовым, и метод получения PointStyleColor в моей виртуальной машине больше не срабатывает.

То же самое для Size элемента управления IntegerUpDown.

Палитра цветов и intupdown не обновлялись при выборе нового цвета. Я заметил, что свойства не были изменены при изменении выбора. PointStyleName было все же.

Редактировать: вот моя ViewModelBase:

using PropertyChanged;
using System.ComponentModel;

namespace WpfApp1.ViewModels
{
    /// <summary>
    /// A base model that fires Property Changed events as needed
    /// </summary>
    [AddINotifyPropertyChangedInterface]
    public class ViewModelBase : INotifyPropertyChanged
    {
        /// <summary>
        /// The event is fired when any child property changes its value
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged = (sender, e) => { };
    }
}

Вот гиф того, что происходит. Я тестирую контроль intupdown здесь: enter image description here

Как вы можете видеть выше, как только я изменяю значение IntUpDown на 8, оно остается на этом значении, даже если выбранный элемент изменяется, что должно изменить значение на 6.

Редактировать: вот небольшой пример приложения, показывающий проблему: https://www.dropbox.com/s/l3gu3nj915cstoa/TestApp.zip?dl=0

1 Ответ

0 голосов
/ 15 ноября 2018

Во-первых, вам необходимо правильно реализовать INotifyPropertyChanged в ViewModelBase.

public event PropertyChangedEventHandler PropertyChanged;

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

Во-вторых, необходимо использовать его для выбранного элемента, измененного в PointStylesViewModel:

private PointStyleModel _selectedPointStyle;
public PointStyleModel SelectedPointStyle
{
    get => _selectedPointStyle;
    set
    {
        _selectedPointStyle = value;
        OnPropertyChanged();
        OnPropertyChanged(nameof(PointStyleColor)); 
        OnPropertyChanged(nameof(PointStyleSize)); 
    }
 }
...