#c# #wpf #mvvm #treeview #reactiveui
Вопрос:
По какой-то причине значение создается правильно, а затем отклоняется каким-то «неявным преобразователем», и я не могу понять, почему. Вот краткий обзор кода, но сначала сообщения о диагностике:
System.Windows.Data Warning: 95 : BindingExpression (hash=63646052): Got PropertyChanged event from MainViewModel (hash=17472816)
System.Windows.Data Warning: 101 : BindingExpression (hash=63646052): GetValue at level 0 from MainViewModel (hash=17472816) using RuntimePropertyInfo(TestNodeRoot): HierarchicalTestNode (hash=53650690)
System.Windows.Data Warning: 80 : BindingExpression (hash=63646052): TransferValue - got raw value HierarchicalTestNode (hash=53650690)
System.Windows.Data Warning: 84 : BindingExpression (hash=63646052): TransferValue - implicit converter produced <null>
System.Windows.Data Warning: 89 : BindingExpression (hash=63646052): TransferValue - using final value <null>
Далее идет привязка древовидного представления. Трассировка включена, как вы можете видеть:
<TreeView ItemsSource="{Binding TestNodeRoot, diag:PresentationTraceSources.TraceLevel=High}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type models:HierarchicalTestNode}" ItemsSource="{Binding Children, diag:PresentationTraceSources.TraceLevel=High}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
TestNodeRoot
Привязка выполняется к ObservableAsPropertyHelper<HierarchicalTestNode?>
модели представления, которая связана с изменением Solution
свойства (обратите внимание, что это работает, потому что привязка получает это значение, как показано выше).:
readonly ObservableAsPropertyHelper<HierarchicalTestNode?> testNodeRoot;
public HierarchicalTestNode? TestNodeRoot => testNodeRoot.Value;
this.WhenAnyValue(x => x.Solution).Select(s => s is null ? null : HierarchicalTestNode.Create(s.TestNodes!))
.ToProperty(this, x => x.TestNodeRoot, out testNodeRoot);
И , наконец HierarchicalTestNode
, это простое ReactiveObject
, содержащее свойства (обратите Children
внимание, что свойство является наблюдаемой коллекцией, как и ожидалось в XAML HierarchicalDataTemplate
, хотя я туда не попал):
public class HierarchicalTestNode : ReactiveObject
{
string name;
public string Name { get => name; set => this.RaiseAndSetIfChanged(ref name, value); }
bool cloak;
public bool Cloak { get => cloak; set => this.RaiseAndSetIfChanged(ref cloak, value); }
int displayIndex;
public int DisplayIndex { get => displayIndex; set => this.RaiseAndSetIfChanged(ref displayIndex, value); }
TestNodeType nodeType;
public TestNodeType NodeType { get => nodeType; set => this.RaiseAndSetIfChanged(ref nodeType, value); }
public ObservableCollection<HierarchicalTestNode> Children { get; } = new();
// other stuff for creating it from a flat database, this also works
}
Итак, есть идеи, что пытается сделать этот внутренний конвертер? Я не думаю TreeView
, что он ожидает какого-либо определенного класса из того, что я видел в Интернете, и я не передаю интерфейсы (я читал, что это может вызвать проблемы), так в чем дело?
Комментарии:
1. Привязка ItemsSource ожидает свойство источника, которое является IEnumerable или может быть преобразовано в IEnumerable. Верно ли это для HierarchicalTestNode, т. Е. для привязки ItemsSource к просмотру дерева? Или вы намеревались написать
ItemsSource="{Binding TestNodeRoot.Children}"
?2. О, чувак, я знал, что это должно быть что-то глупое… Нет, идея состояла в том, чтобы иметь дерево с одним корневым узлом. Позвольте мне быстро попробовать, но вы, скорее всего, правы.
Ответ №1:
Как отметил Клеменс в своем комментарии, проблема в том, что, хотя у меня есть только один корневой узел, ItemsSource
свойство ожидает перечисления. Преобразование корня в массив из одного элемента решило мою проблему.