У меня есть древовидное представление, построенное с помощью HierarchicalDataTemplates, я хочу иметь возможность добавлять файлы JSON к узлам SegmentInfo - если я это сделаю, данные будут добавлены, но изменение не будет отражено в пользовательском интерфейсе (тем не менее, комментарий говорит: «нет данных»"в красном).
Я сделал список элементов дерева в виде ObservableCollection, переместил его в класс" ViewModel ", который наследует INotifyPropertyChanged, я, кажется, настроил его правильно, я установил DataContext вобъект ViewModel в моем окне.В xaml я установил привязки и режим как TwoWay.Все равно ничего не помогло
XAML:
<Window.Resources>
<local:BoolToStringConverter x:Key="BoolToStringConverter" FalseValue="no data" TrueValue="has data" />
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" MinHeight="384.8"/>
<RowDefinition Height="35.2"/>
</Grid.RowDefinitions>
<TreeView Name="trvTypeInfos" Margin="5" Grid.Row="0" ItemsSource="{Binding Path=TypeInfoList, Mode=TwoWay}">
<TreeView.Resources>
<Style TargetType="{x:Type TreeViewItem}">
<EventSetter Event="ListBoxItem.PreviewMouseUp"
Handler="ListBoxItem_PreviewMouseUp"/>
<Setter Property="IsExpanded" Value="True"/>
</Style>
<HierarchicalDataTemplate DataType="{x:Type data:TypeInfo}" ItemsSource="{Binding SegmentInfos, Mode=TwoWay}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
<TextBlock Text=" [" Foreground="Blue" />
<TextBlock Text="{Binding SegmentInfos.Count}" Foreground="Blue"/>
<TextBlock Text="]" Foreground="Blue" />
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type data:SegmentInfo}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
<TextBlock Text=" ("/>
<TextBlock Text="{Binding Path=HasData, Mode=TwoWay, Converter={StaticResource BoolToStringConverter}}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<Trigger Property="Text" Value="no data">
<Setter Property="Foreground" Value="Red"/>
</Trigger>
<Trigger Property="Text" Value="has data">
<Setter Property="Foreground" Value="Green"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock Text=")"/>
</StackPanel>
</DataTemplate>
</TreeView.Resources>
</TreeView>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Width="80" Height="20" Content="OK" Margin="5,0, 5, 5" IsDefault="True" Click="OK_Click"/>
<Button Width="80" Height="20" Content="Cancel" Margin="5,0, 5, 5" Click="Cancel_Click" />
</StackPanel>
</Grid>
Класс окна:
public SegmentDataUpdaterDialog(SegmentDataUpdater segmentDataUpdater, List<TypeInfo> typeInfoList)
{
ViewModel = new ViewModel(typeInfoList);
DataContext = ViewModel;
SegmentDataUpdater = segmentDataUpdater;
InitializeComponent();
}
private void ListBoxItem_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
TreeViewItem item = sender as TreeViewItem;
SegmentInfo segInfo = item.Header as SegmentInfo;
if (segInfo != null)
{
MessageBox.Show(segInfo.JsonContents);
var filePath = AskForFile();
bool success = SegmentDataUpdater.TryStoreJson(segInfo, filePath, out string json);
if (success)
{
segInfo.JsonContents = json;
segInfo.HasData = true;
}
}
}
Класс ViewModel:
public class ViewModel : INotifyPropertyChanged
{
private ObservableCollection<TypeInfo> _typeInfoList;
public ObservableCollection<TypeInfo> TypeInfoList
{
get { return _typeInfoList; }
set
{
if (_typeInfoList==null || !value.All(_typeInfoList.Contains))
{
_typeInfoList = value;
OnPropertyChanged(nameof(TypeInfoList));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
public ViewModel(List<TypeInfo> typeInfos)
{
TypeInfoList = new ObservableCollection<TypeInfo>(typeInfos);
}
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Класс TypeInfo:
public class TypeInfo
{
public string Name { get; set; }
public ObservableCollection<SegmentInfo> SegmentInfos { get; set; }
public int ElementId { get; set; }
public TypeInfo()
{
SegmentInfos = new ObservableCollection<SegmentInfo>();
}
}
Класс SegmentInfo:
public class SegmentInfo
{
public string Name { get; set; }
public bool HasData { get; set; }
public string JsonContents { get; set; }
public int ElementId { get; set; }
}
Классы конвертера:
public class BoolToValueConverter<T> : IValueConverter
{
public T FalseValue { get; set; }
public T TrueValue { get; set; }
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null)
return FalseValue;
else
return (bool)value ? TrueValue : FalseValue;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value != null ? value.Equals(TrueValue) : false;
}
}
public class BoolToStringConverter : BoolToValueConverter<String> { }
Я ожидаю, что после успешного добавления файла json в SegmentInfo пользовательский интерфейс обновит узел с помощьюданные "комментарий.Теперь я могу убедиться, что данные действительно добавлены в SegmentInfo, но пользовательский интерфейс этого не отражает.