Получил жесткий. Рассмотрим ViewModel, который состоит из списка объектов, где каждый объект определяет значение int, а некоторые из этих объектов также определяют словарь пресетов для ints, введенных на основе «дружественной» строки, представляющей это значение в пользовательском интерфейсе.Каков правильный способ привязки к значению, показывая дружественное имя из списка пресетов, также определенных в этом элементе?
Вот пример ...
List<SomeItem> AllItems;
public class SomeItem : INotifyPropertyChanged
{
public SomeItem(int initialValue, Dictionary<int,string> presets)
{
this.CurrentValue = initialValue;
this.Presets = presets;
}
public int CurrentValue{ get; set; } // Shortened for readability. Assume this property supports INPC
public Dictionary<int,string> Presets{ get; private set; }
}
Цель для пользовательского интерфейса, если элемент не имеет предварительных настроек, пользователь может ввести любое значение INT они хотят. Однако, если есть - пресетов, мы хотим ограничить их этими значениями, а также отобразить их в пользовательском интерфейсе в качестве дружественных имен из словаря.
Наша первая попытка была использовать TextBox и ComboBox, изменяя их обзорности в зависимости от того, есть ли предварительные настройки или нет, как это ...
<ComboBox ItemsSource="{Binding Presets}"
DisplayMemberPath="Key"
SelectedValuePath="Value"
SelectedValue="{Binding CurrentValue, Mode=TwoWay}"
Visibility={Binding HasPresets, Converter=...}">
<TextBox Text="{Binding CurrentValue}"
Visibility={Binding HasPresets, Converter...}" /> // Assume the inverse of the combo
... но когда мы используем это в DataTemplate списка, который поддерживает виртуализацию, комбо иногда отображает пробелы. Я считаю, что, когда элемент повторно используется и DataContext изменяется, SelectedValue обновляет до ItemsSource, что означает, что потенциально нет предустановленного значения для соответствия, поэтому предложенное значение SelectedValue получает подбрасываемый элемент управления, , затем ItemsSource обновляет, но нет выбранного значения поэтому он показывает пробел.
Следующая мысль (и то, что мы предпочитали в любом случае) заключалась в том, чтобы использовать только TextBox, который отображал имя предварительной настройки, но на самом деле был привязан к значению, а затем использовать конвертер для работы с его магией и позволить пользователю вводить либо дружественное имя или фактическое значение. Если пользователь набрал то, что не было допустимым значением или пресет, мы просто выбросим ошибку. Если пресетов не было, оно просто будет действовать как сквозной показатель.
Однако, я не уверен, как передать пресеты в конвертер. Вы не можете установить привязку на ConverterParameter, чтобы передать их таким образом, и если вы используете множественную привязку, то я не уверен, как структурировать вызов ConvertBack, поскольку там тоже мне нужно, чтобы они проходили, а не отослал обратно.
Я думаю, правильный способ заключается в реализации UiValue в ViewModel, который мы бы просто связать это понравится ...
<TextBox Text="{Binding UiValue}" />
... затем переместить код, который бы уже был в конвертере для реализации этого актива/getter/setter, или просто передайте значение Value, если пресетов нет. Однако, похоже, слишком много логики идет в ViewModel, где он должен находиться в представлении (ala-конвертер или аналогичный.) И снова, может быть, это точно точка ViewModel. Не знаю. Мысли приветствуются.
+1 для очень хорошо объясненной проблемы. – Sheridan