У меня есть 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>
Вот пример проблемы:
Сначала я выбираю элемент в списке. Все заполнено правильно.
Теперь я изменю размер цвета только на интерфейсе:
А потом я выберу другой элемент из списка:
На первом рисунке я выбираю 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 здесь:
Как вы можете видеть выше, как только я изменяю значение IntUpDown на 8, оно остается на этом значении, даже если выбранный элемент изменяется, что должно изменить значение на 6.
Редактировать: вот небольшой пример приложения, показывающий проблему:
https://www.dropbox.com/s/l3gu3nj915cstoa/TestApp.zip?dl=0