Динамический флажок с динамической привязкой к данным. Видимость никогда не отображается.C#

Место общения программистов C#
Anonymous
Динамический флажок с динамической привязкой к данным. Видимость никогда не отображается.

Сообщение Anonymous »

Я создаю приложение AvaloniaUI с помощью набора инструментов сообщества MVVM, где мне нужно динамически отображать элементы управления и привязывать их к данным модели представления, свойства которой будут неизвестны до момента выполнения. Фактически, я буду читать свойства и поля, к которым они должны быть привязаны, из файла JSON.
Продолжая квест, начатый с моего предыдущего вопроса, я решил «динамизировать» все мои типы элементов управления, начиная с флажков. Я сделал что-то, где пользовательский элемент управления получает StackPanel, заполненный двумя экземплярами CheckBox, второй из которых виден только тогда, когда отмечен первый. Но проверка первого никогда не показывает второго, и происходит другое странное поведение.
Во-первых, модель представления пользовательского элемента управления, которая упрощает динамические свойства:

Код: Выделить всё

public partial class DynamicSettingsGroupVM : ViewModelBase {
[ObservableProperty]
private string _name;
public DynamicSettings DynamicSettingsProperties { get; } = new ();

public DynamicSettingsGroupVM(string aName) {
Name = aName;
((INotifyPropertyChanged)DynamicSettingsProperties).PropertyChanged +=
new PropertyChangedEventHandler(HandlePropertyChanges);
}

private void HandlePropertyChanges(
object? sender, PropertyChangedEventArgs e) {
Trace.WriteLine($"{e.PropertyName} has changed to {DynamicSettingsProperties[e.PropertyName]}.");
}
}
Тело XAML пользовательского элемента управления: Код пользовательского элемента управления, который генерирует динамические элементы управления CheckBoxв соответствии со свойствами, привязанными к их объектам IsChecked, имена которых загружаются из файла:

Код: Выделить всё

  public void CreateDynamicCheckBoxes(string upperBoundProp, string lowerBoundProp) {
var myDC = DataContext as ViewModels.DynamicSettingsGroupVM;
var upperCB = new CheckBox {
[!CheckBox.IsCheckedProperty] = new Binding($"DynamicSettingsProperties[{upperBoundProp}]"),
Content = "Upper"
};
var lowerCB = new CheckBox {
[!CheckBox.IsCheckedProperty] = new Binding($"DynamicSettingsProperties[{lowerBoundProp}]"),
[!IsVisibleProperty] = new Binding($"DynamicSettingsProperties[{upperBoundProp}]"),
Content = "Lower, visible when Upper checked"
};
myDC.DynamicSettingsProperties[upperBoundProp] = false;
myDC.DynamicSettingsProperties[lowerBoundProp] = false;
stpDynamicFields.Children.Add(upperCB);
stpDynamicFields.Children.Add(lowerCB);
}
Код для внешнего пользовательского элемента управления, который инициализирует экземпляр внутреннего пользовательского элемента управления и его модель представления:

Код: Выделить всё

      var dynaSettings = new DynamicSettingsGroup();
dynaSettings.DataContext = new DynamicSettingsGroupVM("New CheckBoxes!");
dynaSettings.CreateDynamicCheckBoxes("IsUpperChecked", "IsLowerChecked");
stpSettingsGroups.Children.Add(dynaSettings);
При выполнении приведенного выше кода в окно отладки записывается и отображается следующее:

Код: Выделить всё

IsUpperChecked has changed to False.
IsLowerChecked has changed to False.
Изображение

Когда я нажимаю флажок «Верхний», отлаживается следующее, но «Нижний...» не появляется:

Код: Выделить всё

IsUpperChecked has changed to True.
Хуже, он ничего не печатает, когда флажок не установлен, что должно присвоить свойству привязки данных значение false.
Попытка первого исправления
Я подумал, что, возможно, индексы привязок должны быть реальными строками, поскольку именно так к ним обращается другой код:

Код: Выделить всё

    var upperCB = new CheckBox {
[!CheckBox.IsCheckedProperty] = new Binding($"DynamicSettingsProperties[\"{upperBoundProp}\"]"),
Content = "Upper"
};
var lowerCB = new CheckBox {
[!CheckBox.IsCheckedProperty] = new Binding($"DynamicSettingsProperties[\"{lowerBoundProp}\"]"),
[!IsVisibleProperty] = new Binding($"DynamicSettingsProperties[\"{upperBoundProp}\"]"),
Content = "Lower, visible when Upper checked"
};
Но теперь оба флажка становятся видимыми, в странном третьем состоянии, а вывод отладки теперь включает:

Код: Выделить всё

IsUpperChecked has changed to False.
IsLowerChecked has changed to False.
[Binding]An error occurred binding 'IsVisible' to 'DynamicSettingsProperties["IsUpperChecked"]': 'Could not convert '(null)' (null) to 'System.Boolean'.' (CheckBox #2428637)
Изображение

При первом щелчке по флажку выводится сообщение «изменено на ложное», а нижний флажок остается видимым, несмотря ни на что.
Попытка второго исправления
Я затем использовал фактический экземпляр Binding, чтобы я мог инициализировать его со значением по умолчанию и не начинать с нуля:

Код: Выделить всё

    var lowerCB = new CheckBox {
[!CheckBox.IsCheckedProperty] = new Binding($"DynamicSettingsProperties[\"{lowerBoundProp}\"]"),
Content = "Lower, visible when Upper checked"
};
var visBinding = new Binding($"DynamicSettingsProperties[\"{upperBoundProp}\"]") {
TargetNullValue = false
};
lowerCB.Bind(IsVisibleProperty, visBinding);
Ошибка исчезла из исходных результатов отладки, теперь они содержат:

Код: Выделить всё

IsUpperChecked has changed to False.
IsLowerChecked has changed to False.
"IsUpperChecked"  has changed to False.
Но хотя «Нижний...» скрыт, «Верхний» по-прежнему начинается в третьем состоянии, печатая «False» при первом щелчке и никогда не отображая «Нижний...» при повторном щелчке.
Попытка третьего исправления
Я удалил \" из аргументов инициализации привязки, а "Верхний" инициализировался с значением true непроверенное состояние, выводится только это:

Код: Выделить всё

IsUpperChecked has changed to False.
IsLowerChecked has changed to False.
Но опять же, он распечатывается только при нажатии на него и проверяет его, а «Нижний...» никогда не появляется.
Попытка четвертого исправления
Я также добавил нулевую защиту к привязке проверенного состояния «Верхнего»:

Код: Выделить всё

    var upperCB = new CheckBox {
Content = "Upper"
};
var upperCheckBinding = new Binding($"DynamicSettingsProperties[{upperBoundProp}]") {
TargetNullValue = false,
Mode = BindingMode.TwoWay
};
upperCB.Bind(CheckBox.IsCheckedProperty, upperCheckBinding);
Но это ничего не изменило.
Всякая помощь в работе привязки IsVisible приветствуется, спасибо.

Вернуться в «C#»