ObservableCollection.CollectionChanged select 工具栏上的 DataTemplate 不正确
ObservableCollection.CollectionChanged does not select the correct DataTemplate on ToolBar
我的项目有一个带有 3 个数据模板的工具栏:
<ToolBar ItemsSource="{Binding ContextActions}" Background="Transparent" ToolBarTray.IsLocked="True">
<ToolBar.Resources>
<DataTemplate DataType="{x:Type viewModels:SimpleContextActionViewModel}">
<Button Command="{Binding ActionCommand}" Style="{StaticResource ToolBarButtonStyle}" ToolTip="{userInterface:Translation Binding={Binding ToolTip}}">
<ContentControl Template="{Binding Icon,Converter={StaticResource NameToResourceConverter}}" Margin="5" />
</Button>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModels:SeparatorViewModel}">
<Rectangle Fill="{StaticResource SeparatorBrush}" Width="1" VerticalAlignment="Stretch" Margin="2,7" />
</DataTemplate>
<DataTemplate DataType="{x:Type viewModels:PopupContextActionViewModel}">
<Grid>
<ToggleButton IsChecked="{Binding ElementName=ContextActionPopup, Mode=TwoWay,Path=IsOpen}" Style="{StaticResource ToolBarButtonStyle}"
ToolTip="{userInterface:Translation Binding={Binding ToolTip}}">
<ContentControl Template="{Binding Icon, Converter={StaticResource NameToResourceConverter}}" Margin="5" />
</ToggleButton>
<Popup Name="ContextActionPopup" Height="150" Width="150" StaysOpen="False">
<Border BorderBrush="{StaticResource PopupBorderBrush}" BorderThickness="1" Background="White">
<ContentControl userInterface:RegionHelper.RegionName="{Binding RegionId}" />
</Border>
</Popup>
</Grid>
</DataTemplate>
</ToolBar.Resources>
</ToolBar>
ItemsSource 是一个 ObservableCollection
前三项在我的 ViewModel 的构造函数中已经可用,这三项按预期使用 DataTemplates。
如果我向 ObservableCollection 添加另一个 "SimpleContextActionViewModel",ToolBar 只会添加一个调用 ToString 的 ContentPresenter。如果我添加以下行以将 ObservableCollection 重新分配给一个新的,一切正常:
this.ContextActions = new ObservableCollection<object>(this.ContextActions);
这触发了我的 ViewModel 的 NotifyPropertyChanged 实现,所有项目都被重新创建并且看起来很好。
为什么我的 ObservableCollection 的 CollectionChanged 不是 select 有效的 DataTemplate 而 PropertyChanged 是?
这是它的样子
我不确定这是否适用于您的情况,但您的问题似乎非常类似于:Wiring up CollectionChanged and PropertyChanged (Or : Why do some WPF Bindings not refresh?)
来自 link 的已接受答案:
If you don't provide WPF with a template for a data item (such as the
Person objects in your list), it'll default to using the ToString()
method to display. That's a member, not a property, and so you get no
event notification when the value changes.
If you add DisplayMemberPath="Name" to your listbox, it'll generate a
template that binds properly to the Name of your person - which will
then update automatically as you'd expect.
您能否将 DisplayMemberPath 应用于工具箱,使其默认情况下不使用 ToString() 进行渲染,而是触发 NotifyPropertyChanged?
我以前见过这种情况发生在工具栏上,当与集合一起使用时,除了构造函数之外的任何地方都会发生变化。
不要在工具栏资源中添加您的数据模板,而是将它们添加到 app.xaml 然后您将看到您的代码将正常工作。试试这个,让我知道它是否仍然无法正常工作
我的项目有一个带有 3 个数据模板的工具栏:
<ToolBar ItemsSource="{Binding ContextActions}" Background="Transparent" ToolBarTray.IsLocked="True">
<ToolBar.Resources>
<DataTemplate DataType="{x:Type viewModels:SimpleContextActionViewModel}">
<Button Command="{Binding ActionCommand}" Style="{StaticResource ToolBarButtonStyle}" ToolTip="{userInterface:Translation Binding={Binding ToolTip}}">
<ContentControl Template="{Binding Icon,Converter={StaticResource NameToResourceConverter}}" Margin="5" />
</Button>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModels:SeparatorViewModel}">
<Rectangle Fill="{StaticResource SeparatorBrush}" Width="1" VerticalAlignment="Stretch" Margin="2,7" />
</DataTemplate>
<DataTemplate DataType="{x:Type viewModels:PopupContextActionViewModel}">
<Grid>
<ToggleButton IsChecked="{Binding ElementName=ContextActionPopup, Mode=TwoWay,Path=IsOpen}" Style="{StaticResource ToolBarButtonStyle}"
ToolTip="{userInterface:Translation Binding={Binding ToolTip}}">
<ContentControl Template="{Binding Icon, Converter={StaticResource NameToResourceConverter}}" Margin="5" />
</ToggleButton>
<Popup Name="ContextActionPopup" Height="150" Width="150" StaysOpen="False">
<Border BorderBrush="{StaticResource PopupBorderBrush}" BorderThickness="1" Background="White">
<ContentControl userInterface:RegionHelper.RegionName="{Binding RegionId}" />
</Border>
</Popup>
</Grid>
</DataTemplate>
</ToolBar.Resources>
</ToolBar>
ItemsSource 是一个 ObservableCollection
前三项在我的 ViewModel 的构造函数中已经可用,这三项按预期使用 DataTemplates。
如果我向 ObservableCollection 添加另一个 "SimpleContextActionViewModel",ToolBar 只会添加一个调用 ToString 的 ContentPresenter。如果我添加以下行以将 ObservableCollection 重新分配给一个新的,一切正常:
this.ContextActions = new ObservableCollection<object>(this.ContextActions);
这触发了我的 ViewModel 的 NotifyPropertyChanged 实现,所有项目都被重新创建并且看起来很好。
为什么我的 ObservableCollection 的 CollectionChanged 不是 select 有效的 DataTemplate 而 PropertyChanged 是?
这是它的样子
我不确定这是否适用于您的情况,但您的问题似乎非常类似于:Wiring up CollectionChanged and PropertyChanged (Or : Why do some WPF Bindings not refresh?)
来自 link 的已接受答案:
If you don't provide WPF with a template for a data item (such as the Person objects in your list), it'll default to using the ToString() method to display. That's a member, not a property, and so you get no event notification when the value changes.
If you add DisplayMemberPath="Name" to your listbox, it'll generate a template that binds properly to the Name of your person - which will then update automatically as you'd expect.
您能否将 DisplayMemberPath 应用于工具箱,使其默认情况下不使用 ToString() 进行渲染,而是触发 NotifyPropertyChanged?
我以前见过这种情况发生在工具栏上,当与集合一起使用时,除了构造函数之外的任何地方都会发生变化。
不要在工具栏资源中添加您的数据模板,而是将它们添加到 app.xaml 然后您将看到您的代码将正常工作。试试这个,让我知道它是否仍然无法正常工作