列表视图被选中 [英] ListView isSelected
问题描述
我的 xaml
中有一个列表视图,我用这样的项目填充:
Listdicts = DataLayer.Manager.getDictionaries();如果(听写!= null){foreach (DataLayer.Models.Dictionary dicts 中的 dict){this.itemListView.Items.Add(dict);}}
我的 DataLayer.Models.Dictionary
对象有一个 isSelected
属性以及一个 Name
和一个 SubName
.
Name 和 SubName 在模板中工作正常,但如何在用户单击项目时选择并更新项目?
谢谢!
我的 xaml 现在看起来像这样,但项目仍然没有被选中
<ListView.ItemContainerStyle><Style TargetType="ListViewItem"><Setter Property="IsSelected" Value="{Binding Source=Selected,Mode=TwoWay}"/></风格></ListView.ItemContainerStyle><ListView.ItemTemplate><数据模板><网格边距="6"><Grid.ColumnDefinitions><ColumnDefinition Width="*"/></Grid.ColumnDefinitions><StackPanel Grid.Column="0" Margin="0,0,0,0"><TextBlock Text="{绑定名称}"/><TextBlock Text="{Binding SubName}" Style="{StaticResource CaptionTextStyle}" TextWrapping="Wrap"/></StackPanel></网格></数据模板></ListView.ItemTemplate></ListView>
刚刚注意到这个问题实际上并没有被标记为 WPF;但我希望它仍然适用.
WPF 本质上是 MVVM.在后面的代码中直接操作控件通常不是一个好主意.因此,建议创建一个名为 ViewModel 的视图友好"模型;
现在可以在代码隐藏中对选择更改做出反应,但这会将逻辑与视图混合.
更新以包括检测任何字典中的变化的能力(包括选定的变化时)
希望这会有所帮助.
I have an listview in my xaml
that i populate with items like this:
List<DataLayer.Models.Dictionary> dicts = DataLayer.Manager.getDictionaries();
if (dicts != null)
{
foreach (DataLayer.Models.Dictionary dict in dicts)
{
this.itemListView.Items.Add(dict);
}
}
My DataLayer.Models.Dictionary
object have an isSelected
property along with a Name
and a SubName
.
Name and SubName works fine in the template but how can i go about getting the item to be selected and also updated when user clicks an item?
Thanks!
Edit:
My xaml now looks like this, but the item is still not selected
<ListView
x:Name="itemListView"
TabIndex="1"
Grid.Row="1"
Margin="0,60,0,0"
Padding="0,0,0,0"
IsSwipeEnabled="False"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
SelectionChanged="itemListView_SelectionChanged_1"
SelectionMode="Multiple"
FontFamily="Global User Interface">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsSelected" Value="{Binding Source=Selected,Mode=TwoWay}"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid Margin="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Margin="0,0,0,0">
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding SubName}" Style="{StaticResource CaptionTextStyle}" TextWrapping="Wrap"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
[Edit] Just noticed this question isn't actually tagged WPF; but I hopefully it still applies.
WPF is inherently MVVM. Directly manipulating controls in code behind is generally not a good idea. So it is advised to create a "view-friendly" model called a ViewModel; See Here. Also for bindings to be of any use, in a changing environment, you must inform of changes to properties and or collections, so that controls can be updated.
First and formost you have a collection of dictionaries, So you create this collection such that it can notify of changes; ObservableCollection can do that. As a general rule of thumb any collection used by WPF you should just use an ObservableCollection, and/or derive from it.
so here is compete working example:
Bare in mind I'm using FODY to inject my PropertyChanged raisers; See done manually
public class Dict : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string Name { get; set; }
public string SubName { get; set; }
public bool Selected { get; set; }
}
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<Dict> Dictionaries { get; set; }
public ViewModel()
{
Dictionaries = new ObservableCollection<Dict>()
{
new Dict()
{
Name = "English",
SubName = "en",
Selected = false,
},
new Dict()
{
Name = "English-British",
SubName = "en-uk",
Selected = true
},
new Dict()
{
Name = "French",
SubName = "fr",
Selected = true
}
};
Dictionaries.CollectionChanged += DictionariesCollectionChanged;
}
private void DictionariesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch(e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach(var dict in e.NewItems.Cast<Dict>())
dict.PropertyChanged += DictionaryChanged;
break;
case NotifyCollectionChangedAction.Remove:
foreach (var dict in e.OldItems.Cast<Dict>())
dict.PropertyChanged -= DictionaryChanged;
break;
}
}
private void DictionaryChanged(object sender, PropertyChangedEventArgs e)
{
Dict dictionary = (Dict)sender;
//handle a change in Dictionary
}
}
With this you can add or remove objects at any time, although here I am just initializing them in the constructor.
Then you would have this in your window or control. I've included the namespaces to make it more self-contained; but this would be for WPF namespaces.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1">
<Window.Resources>
<local:ViewModel x:Key="viewmodel"/>
</Window.Resources>
<ListView
x:Name="itemListView"
DataContext="{StaticResource ResourceKey=viewmodel}"
ItemsSource="{Binding Path=Dictionaries}"
SelectionMode="Multiple">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsSelected" Value="{Binding Path=Selected, Mode=TwoWay}"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid Margin="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Margin="0,0,0,0">
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding SubName}" TextWrapping="Wrap"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Window>
If you don't use ObservableCollection for your collection, then start adding elements to it after WPF has be loaded-up, it will never notify the binding manager that the ListView should be updated.
The above on start up:
you can easily see that the underlying Dictionaries collection is being changed (i.e.its not just the ListView), by overriding the returned value from selected:
public bool Selected { get { return true; } set {/* do nothing*/ }}
Which means everything is always selected, even if you try to deselect it in the view. It will always look like this:
Styling is a different issue, the list looks different if it doesn't have focus. See Here
Now reacting to selection changes could be done in the code-behind, but that would be mixing logic with view.
[Edit] updated to include ability to detect changes in any Dict (including when selected changes)
You could look into this to simplify it
Hope this helps.
这篇关于列表视图被选中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!