Wpf 为什么ItemsControl中ContentControl的TargetNullValue在项之间共享?
鉴于此xaml:Wpf 为什么ItemsControl中ContentControl的TargetNullValue在项之间共享?,wpf,xaml,data-binding,itemscontrol,mahapps.metro,Wpf,Xaml,Data Binding,Itemscontrol,Mahapps.metro,鉴于此xaml: <ItemsControl Grid.Row="1" ItemsSource="{Binding Devices}"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <UniformGrid Rows="1" /> </ItemsPanelTemplate>
<ItemsControl Grid.Row="1" ItemsSource="{Binding Devices}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="1" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type viewModels:IDeviceViewModel}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="{Binding Name}"
Grid.Row="0"
Margin="5"
HorizontalAlignment="Center" />
<ContentControl Grid.Row="1">
<ContentControl.Content>
<Binding Path="CurrentState">
<Binding.TargetNullValue>
<Button Command="{Binding DataContext.ActivateCommand, RelativeSource={RelativeSource AncestorType={x:Type mah:MetroWindow}}}"
CommandParameter="{Binding}">
<Button.Template>
<ControlTemplate>
<Image MaxWidth="100"
Margin="10"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Source="/Resources/ActivateDevice.png" />
</ControlTemplate>
</Button.Template>
</Button>
</Binding.TargetNullValue>
</Binding>
</ContentControl.Content>
</ContentControl>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
所以现在的问题是:为什么首先要共享TargetNullValue?该属性告诉WPF在每次使用XAML元素时创建一个新实例,但这只能在ResourceDictionary中的项上设置。尝试将按钮放入带有x:Shared='False'的ResourceDictionary中,然后使用StaticResource引用它。一个想法:将按钮放入带有x:Shared='False'的ResourceDictionary中。然后使用“StaticResource”引用资源。@KeithStein这实际上是可行的!它还提供了一个简洁的语法,因为绑定仍然是一个属性。然而,我真的很想理解为什么wpf首先要这么做。我的意思是,我希望items控件中各个项的数据模板能够独立实例化,它们如何在每个项的实例中共享内容控件中绑定的目标空值?太好了。我把它贴了出来,作为你可以接受的答案。至于为什么会出现这种情况:我确实希望每个项都有自己的DataTemplate实例,但这些属性设置为的值可能会被重用?因此,每个单独的TargetNullValue都会被分配到已解析的相同按钮。这适用于最常用的字符串或其他值类型,可以节省时间和内存,但会给大多数其他类带来问题。
<ItemsControl Grid.Row="1" ItemsSource="{Binding Devices}">
<ItemsControl.Resources>
<Button x:Key="ActivateDeviceButton"
x:Shared="False"
Command="{Binding DataContext.ActivateCommand, RelativeSource={RelativeSource AncestorType={x:Type mah:MetroWindow}}}"
CommandParameter="{Binding Path=DataContext, ElementName=deviceRoot}">
<Button.Template>
<ControlTemplate>
<Image MaxWidth="100"
Margin="10"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Source="/Resources/ActivateDevice.png" />
</ControlTemplate>
</Button.Template>
</Button>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="1" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type viewModels:IDeviceViewModel}">
<Grid x:Name="deviceRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="{Binding Name}"
Grid.Row="0"
Margin="5"
HorizontalAlignment="Center" />
<ContentControl Grid.Row="1" Content="{Binding CurrentState, TargetNullValue={StaticResource ActivateDeviceButton}}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>