在 Windows Store Apps 的 DataTemplate 更改中保留子列表中的选定项目
Retaining selected item in sublist in DataTemplate change in Windows Store Apps
我在 Windows Phone 8.1 中生成了一个可扩展的列表视图。我在更改项目选择和单击项目时切换模板。
<ListView Name="FiltersListview" ItemContainerStyle="{StaticResource StretchItemStyle}" ItemTemplate="{StaticResource CollapsedTemplate}" SelectionChanged="FiltersListview_SelectionChanged" IsItemClickEnabled="True" ItemClick="FiltersListview_ItemClick" Grid.Row="1" Grid.ColumnSpan="2"/>
<DataTemplate x:Name="CollapsedTemplate">
<Grid Height="50">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" Style="{StaticResource PageTextStyle}"/>
<Image Margin="10" Grid.Column="1" Source="/Images/arrow-down.png"/>
<Rectangle Fill="Black" VerticalAlignment="Bottom" Height="1" Grid.ColumnSpan="2"/>
</Grid>
</DataTemplate>
<DataTemplate x:Name="ExpandedTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" Style="{StaticResource PageTextStyle}"/>
<Image Margin="10" Grid.Column="1" Source="/Images/arrow-up.png"/>
<ListView Margin="20,0" Grid.Row="1" RequestedTheme="Light" Grid.ColumnSpan="2" ItemsSource="{Binding SubList}" SelectionMode="Multiple">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="FontSize" Value="22"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Foreground" Value="Black"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
</DataTemplate>
然后模板更改
DataTemplate dtSmall, dtLarge;
private void FiltersListview_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try
{
if (e.RemovedItems.Count > 0)
{
foreach (var item in e.RemovedItems)
{
((ListViewItem)(sender as ListView).ContainerFromItem(item)).ContentTemplate = dtSmall;
}
}
if (e.AddedItems.Count > 0)
{
foreach (var item in e.AddedItems)
{
((ListViewItem)(sender as ListView).ContainerFromItem(item)).ContentTemplate = dtLarge;
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
private void FiltersListview_ItemClick(object sender, ItemClickEventArgs e)
{
try
{
if ((sender as ListView).SelectedItem != null)
{
if ((sender as ListView).SelectedItem.Equals(e.ClickedItem))
(sender as ListView).SelectedItem = null;
else
(sender as ListView).SelectedItem = e.ClickedItem;
}
else
(sender as ListView).SelectedItem = e.ClickedItem;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
现在,当打开可扩展列表时,我想在子列表中保留所选项目的状态,但是随着模板的更改和新列表视图的创建,它不会保留所选项目。有人可以帮忙吗?
哇。你有点像在这里用压路机敲碎坚果。为什么不创建一个复杂的数据模板,而不是切换模板,选择后会显示次要内容?
如果您从 ListView 派生,则可以覆盖 PrepareContainer:
public class MyListView : Windows.UI.Xaml.Controls.ListView
{
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
var item = element as Windows.UI.Xaml.Controls.ListViewItem;
base.PrepareContainerForItemOverride(element, item);
}
}
在这里,您可以访问 IsSelected
属性,您可以将其绑定到您的模型(只需创建一个 属性)并显示在您的数据模板中。使用此值,您可以在数据模板中的内容之间切换。
我会使用行为,这样我就不必费心思考这个问题。像这样:
<Grid>
<Interactivity:Interaction.Behaviors>
<Core:DataTriggerBehavior Binding="{Binding IsSelected}" Value="True">
<Core:ChangePropertyAction TargetObject="{Binding ElementName=view1}" PropertyName="Visibility" Value="Visible"/>
<Core:ChangePropertyAction TargetObject="{Binding ElementName=view2}" PropertyName="Visibility" Value="Collapsed"/>
</Core:DataTriggerBehavior>
<Core:DataTriggerBehavior Binding="{Binding IsSelected}" Value="False">
<Core:ChangePropertyAction TargetObject="{Binding ElementName=view1}" PropertyName="Visibility" Value="Visible"/>
<Core:ChangePropertyAction TargetObject="{Binding ElementName=view2}" PropertyName="Visibility" Value="Collapsed"/>
</Core:DataTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</Grid>
由于您的上下文从未真正改变,因此您的列表索引也不会改变。
祝你好运!
我在 Windows Phone 8.1 中生成了一个可扩展的列表视图。我在更改项目选择和单击项目时切换模板。
<ListView Name="FiltersListview" ItemContainerStyle="{StaticResource StretchItemStyle}" ItemTemplate="{StaticResource CollapsedTemplate}" SelectionChanged="FiltersListview_SelectionChanged" IsItemClickEnabled="True" ItemClick="FiltersListview_ItemClick" Grid.Row="1" Grid.ColumnSpan="2"/>
<DataTemplate x:Name="CollapsedTemplate">
<Grid Height="50">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" Style="{StaticResource PageTextStyle}"/>
<Image Margin="10" Grid.Column="1" Source="/Images/arrow-down.png"/>
<Rectangle Fill="Black" VerticalAlignment="Bottom" Height="1" Grid.ColumnSpan="2"/>
</Grid>
</DataTemplate>
<DataTemplate x:Name="ExpandedTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" Style="{StaticResource PageTextStyle}"/>
<Image Margin="10" Grid.Column="1" Source="/Images/arrow-up.png"/>
<ListView Margin="20,0" Grid.Row="1" RequestedTheme="Light" Grid.ColumnSpan="2" ItemsSource="{Binding SubList}" SelectionMode="Multiple">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="FontSize" Value="22"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Foreground" Value="Black"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
</DataTemplate>
然后模板更改
DataTemplate dtSmall, dtLarge;
private void FiltersListview_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try
{
if (e.RemovedItems.Count > 0)
{
foreach (var item in e.RemovedItems)
{
((ListViewItem)(sender as ListView).ContainerFromItem(item)).ContentTemplate = dtSmall;
}
}
if (e.AddedItems.Count > 0)
{
foreach (var item in e.AddedItems)
{
((ListViewItem)(sender as ListView).ContainerFromItem(item)).ContentTemplate = dtLarge;
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
private void FiltersListview_ItemClick(object sender, ItemClickEventArgs e)
{
try
{
if ((sender as ListView).SelectedItem != null)
{
if ((sender as ListView).SelectedItem.Equals(e.ClickedItem))
(sender as ListView).SelectedItem = null;
else
(sender as ListView).SelectedItem = e.ClickedItem;
}
else
(sender as ListView).SelectedItem = e.ClickedItem;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
现在,当打开可扩展列表时,我想在子列表中保留所选项目的状态,但是随着模板的更改和新列表视图的创建,它不会保留所选项目。有人可以帮忙吗?
哇。你有点像在这里用压路机敲碎坚果。为什么不创建一个复杂的数据模板,而不是切换模板,选择后会显示次要内容?
如果您从 ListView 派生,则可以覆盖 PrepareContainer:
public class MyListView : Windows.UI.Xaml.Controls.ListView
{
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
var item = element as Windows.UI.Xaml.Controls.ListViewItem;
base.PrepareContainerForItemOverride(element, item);
}
}
在这里,您可以访问 IsSelected
属性,您可以将其绑定到您的模型(只需创建一个 属性)并显示在您的数据模板中。使用此值,您可以在数据模板中的内容之间切换。
我会使用行为,这样我就不必费心思考这个问题。像这样:
<Grid>
<Interactivity:Interaction.Behaviors>
<Core:DataTriggerBehavior Binding="{Binding IsSelected}" Value="True">
<Core:ChangePropertyAction TargetObject="{Binding ElementName=view1}" PropertyName="Visibility" Value="Visible"/>
<Core:ChangePropertyAction TargetObject="{Binding ElementName=view2}" PropertyName="Visibility" Value="Collapsed"/>
</Core:DataTriggerBehavior>
<Core:DataTriggerBehavior Binding="{Binding IsSelected}" Value="False">
<Core:ChangePropertyAction TargetObject="{Binding ElementName=view1}" PropertyName="Visibility" Value="Visible"/>
<Core:ChangePropertyAction TargetObject="{Binding ElementName=view2}" PropertyName="Visibility" Value="Collapsed"/>
</Core:DataTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</Grid>
由于您的上下文从未真正改变,因此您的列表索引也不会改变。
祝你好运!