本文介绍了如何在ListViewItem的DataTemplate中绑定IsSelected属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
好吧,我想在 UWP 中创建 ListViewItem
,这将改变他的选择视图.所以我需要在选择时更改 ListViewItem
某些元素的 Visibility
属性.
我找到了一些方法来制作 ListViewItem
和 Binding IsSelected
属性的自定义样式,如下所示:
<TextBlock Text="{Binding DeviceID}/> </StackPanel></StackPanel></边框><Border BorderThickness="1" BorderBrush="Orange" Visibility="{Binding IsSelected, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}}"/></网格></控制模板></Setter.Value></Setter></风格>
它运行良好,但通过这种方式我无法绑定 DeviceID
文本.
另一种方法是像这样创建DataTemplate
:
<Grid Background="Gray" Margin="1" Width="300" ><堆栈面板><ContentPresenter x:Name="Presenter"/><StackPanel Orientation="水平"><Image Source="/Assets/14th_crane_stop.png" Height="50" Width="50" Stretch="Uniform"/><StackPanel Orientation="Vertical" Margin="25,0,0,0 "Visibility="{Binding IsSelected, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}}"><TextBlock Text="{Binding DeviceID}" Style="{StaticResource VehicleTextStyle}"/><TextBlock Text="{Binding Mark}" Style="{StaticResource VehicleTextStyle}"/></StackPanel></StackPanel></StackPanel ></网格></数据模板>
现在我可以正确绑定文本,但无法绑定 IsSelected
属性.我尝试使用不同的模式来执行此操作,但它仍然不起作用,因为我无法在 DataTemplate 中使用 TemplatedParent
键.
所以我需要一些答案:
-我可以以第一种方式绑定文本吗?我该怎么做?- 如何以第二种方式绑定 IsSelected
属性?
解决方案
我不建议更改 ListViewItem 模板,因为您会失去它提供的所有功能(选择外观、检查功能等).
>
在第二个代码段中使用 Mode=TemplatedParent
将不起作用,因为该上下文中的模板化父项是
多选
与单选相同,但有以下变化:
MainPageViewModel
公共类 MainPageViewModel : NotifyPropertyChangedBase{公共列表项目{得到;放;}公共 MainPageViewModel(){项目 = 新列表(){new Item() { Text = "Apple" },new Item() { Text = "香蕉" },};}public void SelectionChanged(对象发送者,SelectionChangedEventArgs e){foreach(e.RemovedItems 中的项目){item.IsSelected = false;}foreach(e.AddedItems 中的项目){item.IsSelected = true;}}}
MainPage.xaml
<ListView.ItemContainerStyle><Style TargetType="ListViewItem"><Setter Property="HorizontalContentAlignment" Value="Stretch"/></风格></ListView.ItemContainerStyle><ListView.ItemTemplate><DataTemplate x:DataType="local:Item"><网格><Grid.ColumnDefinitions><列定义/><ColumnDefinition Width="自动"/></Grid.ColumnDefinitions><TextBlock Text="{绑定文本}"/><TextBlock Text="我被选中了!"Grid.Column="1" Visibility="{x:Bind IsSelected, Mode=OneWay}"/></网格></数据模板></ListView.ItemTemplate></ListView>
MainPage.xaml.cs
公共密封部分类 MainPage : Page{公共主页(){this.InitializeComponent();DataContext = new MainPageViewModel();}public MainPageViewModel ViewModel =>(MainPageViewModel)DataContext;}
Well, I want to make the ListViewItem
in UWP ,that'll be changing his view on selecting. So I need to change the Visibility
property of some elements of ListViewItem
on selecting.
I found some way to do this with making custom Style of ListViewItem
and Binding IsSelected
property like this:
<Style x:Key="VehicleListViewItemStyle" TargetType="ListViewItem" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Grid Background="Gray" Margin="1">
<Border Margin="2" Padding="10" Background="Gray" >
<StackPanel>
<ContentPresenter x:Name="Presenter1" />
<StackPanel Orientation="Horizontal" Background="Transparent" Margin="-10,0,-9,-9" VerticalAlignment="Center" x:Name="infoPanel"
Visibility="{Binding IsSelected, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}}">
<TextBlock Text="{Binding DeviceID}/> </StackPanel>
</StackPanel>
</Border>
<Border BorderThickness="1" BorderBrush="Orange" Visibility="{Binding IsSelected, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Its working good, but with this way I cant bind the DeviceID
text.
Another one way is creating DataTemplate
like this:
<DataTemplate x:Key="monitoringListViewItem" x:Name="item">
<Grid Background="Gray" Margin="1" Width="300" >
<StackPanel>
<ContentPresenter x:Name="Presenter"/>
<StackPanel Orientation="Horizontal">
<Image Source="/Assets/14th_crane_stop.png" Height="50" Width="50" Stretch="Uniform"/>
<StackPanel Orientation="Vertical" Margin="25,0,0,0 "
Visibility="{Binding IsSelected, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}}"
>
<TextBlock Text="{Binding DeviceID}" Style="{StaticResource VehicleTextStyle}"/>
<TextBlock Text="{Binding Mark}" Style="{StaticResource VehicleTextStyle}"/>
</StackPanel>
</StackPanel>
</StackPanel >
</Grid>
</DataTemplate>
Now I can bind the text correctly, but cant bind the IsSelected
property. I've tried to do this with different Modes, but it still doesn't work because I cant use the TemplatedParent
key inside the DataTemplate.
So I need some answers:
-can I bind the text in first way and how can I do that?-how can I bind the IsSelected
property in the second way?
解决方案
I don't recommend changing the ListViewItem template since you lose all the bells and whistles it provides (selection appearance, ability to be checked, etc).
Using Mode=TemplatedParent
in the second snippet won't work because the templated parent from that context is a ListViewItemPresenter, not the ListViewItem (which is the presenter's parent).
It looks like what you're trying to do is to show additional information in the list item when it is selected.
Single selection
C# classes
public class NotifyPropertyChangedBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetProperty<T>(ref T property, T value, [CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(property, value))
{
return false;
}
property = value;
OnPropertyChanged(propertyName);
return true;
}
}
public class Item : NotifyPropertyChangedBase
{
private string text;
public string Text
{
get { return text; }
set { SetProperty(ref text, value); }
}
private bool isSelected;
public bool IsSelected
{
get { return isSelected; }
set { SetProperty(ref isSelected, value); }
}
}
public class MainPageViewModel : NotifyPropertyChangedBase
{
public List<Item> Items { get; set; }
private Item selectedItem;
public Item SelectedItem
{
get { return selectedItem; }
set
{
if (selectedItem != value)
{
if (selectedItem != null)
{
selectedItem.IsSelected = false;
}
SetProperty(ref selectedItem, value);
if (selectedItem != null)
{
selectedItem.IsSelected = true;
}
}
}
}
public MainPageViewModel()
{
Items = new List<Item>()
{
new Item() { Text = "Apple" },
new Item() { Text = "Banana" },
};
}
}
MainPage.xaml
<ListView ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Item">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Text}"/>
<!-- x:Bind doesn't require visibility converter if min SDK is targeting Anniversary update -->
<TextBlock Text="I'm selected!" Grid.Column="1" Visibility="{x:Bind IsSelected, Mode=OneWay}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
MainPage.xaml.cs
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
DataContext = new MainPageViewModel();
}
}
Multiple selection
Same as single selection but with the following changes:
MainPageViewModel
public class MainPageViewModel : NotifyPropertyChangedBase
{
public List<Item> Items { get; set; }
public MainPageViewModel()
{
Items = new List<Item>()
{
new Item() { Text = "Apple" },
new Item() { Text = "Banana" },
};
}
public void SelectionChanged(object sender, SelectionChangedEventArgs e)
{
foreach (Item item in e.RemovedItems)
{
item.IsSelected = false;
}
foreach (Item item in e.AddedItems)
{
item.IsSelected = true;
}
}
}
MainPage.xaml
<ListView ItemsSource="{Binding Items}" SelectionChanged="{x:Bind ViewModel.SelectionChanged}" SelectionMode="Extended">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Item">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Text}"/>
<TextBlock Text="I'm selected!" Grid.Column="1" Visibility="{x:Bind IsSelected, Mode=OneWay}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
MainPage.xaml.cs
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
DataContext = new MainPageViewModel();
}
public MainPageViewModel ViewModel => (MainPageViewModel)DataContext;
}
这篇关于如何在ListViewItem的DataTemplate中绑定IsSelected属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!