如何正确绑定 ListView 以便它的项目可以接收背景值?
How to properly bind a ListView so that it's items can receive a background value?
我目前正在开发一个小型视频扑克应用程序,部分原因是它很有趣,而且我需要一个学校项目。
除非我遗漏了什么,否则我的逻辑应该完成,但是现在,当我将注意力转向应用程序的 UI 方面时,我遇到了障碍。
我 need/want 我的 ListView 要做的是:
- 不与用户执行的 mouseovers/mouse 次点击互动
- 通过代码填写,每次投注变化需要更换项目
- 当用户获胜时,通过更改背景在 ListView 中突出显示它 属性。
到目前为止我已经 "some" 成功了,这意味着我已经能够让它工作,这样我就可以 select 通过鼠标点击一个项目,然后颜色改变,但是我无法通过将 SelectedItem 更改为获胜手来使其工作。
我已经尝试了几乎所有我能想到的方法,但我已经走到了死胡同。
我相当确定它是通过绑定数据以某种方式实现的,但到目前为止我的所有努力都失败了。在数据绑定 XAML 元素方面,我仍然缺乏相当多的知识和经验。
如果这里有人可以帮助我 neat/clean/efficient 实现这一目标的方法,将不胜感激。
XAML:
<ListView x:Name="lvTest" HorizontalAlignment="Left" Height="200" VerticalAlignment="Top" Width="160" Margin="10,10,0,0">
<ListView.Resources>
<Style TargetType="GridViewColumnHeader">
<Setter Property="Visibility" Value="Collapsed" />
</Style>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<GridViewRowPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Width="105" DisplayMemberBinding="{Binding HandNaam}"/>
<GridViewColumn Width="45" DisplayMemberBinding="{Binding Betaling}"/>
</GridView>
</ListView.View>
</ListView>
C#:
List<Hand> hands = new List<Hand>();
//Bet has been changed, (re-)populate the ListView
void Betchanged()
{
hands.Clear();
lvTest.ItemsSource = null;
for (int i = 0; i <= 8; i++)
{
hands.Add(new Hand(Hand.hands[i], bet));
}
lvTest.ItemsSource = hands;
}
//Game ends
//After checking for a winning hand, highlight that hand in the ListView
private void EndGame()
{
//Do some stuff
//Check if there's a winning hand
int winnings;
Hand hand = null;
winnings = Poker.FindWin(splK, hands, out hand); //out hand is of type Hand
//If there's a winning hand, highlight it in the ListView
if (hand != null)
{
foreach (Hand h in lvTest.Items)
{
if (h.HandName == hand.HandName)
{
//This seems like the most logical (maybe not most efficient) way to find the correct item in the ListView
//Here's where the Background property for the ListViewItem should be changed
}
}
}
//Do some more stuff
}
PS:我的 XAML 中的当前模板样式覆盖了我的 ListViewItem 的 hover/click 交互。
编辑:这是一个屏幕截图,其中包含应更改 ListViewItem 的背景时的可能情况:
为了通过 Binding
通知控件其内容已更改,您的 ItemsSource
需要实施 INotifyCollectionChanged
。目前,实现此接口的最常见的泛型集合是 ObservableCollection<T>
.
hands
应该是 ObservableCollection<Hand>
而不是 List<Hand>
.
根据评论编辑:
WPF Binding
处理更改通知。对于属性,这意味着在需要通知其属性已更改的 class 上实施 INotifyPropertyChanged
。您的 Hand
class 应该在您要更改的特定值发生更改时实施 INotifyPropertyChanged
。
表示逻辑应由 View
class(或与 View
相关的代码(如 Converter
)处理,因此您应该绑定到您的模型 属性 值并使用转换器将其转换为 Brush
对象。
您可以只在模型对象上公开 Brush
,但这会破坏 MVVM 模式,因为 ViewModel
不应该具有 View-specific/presentation 技术 classes嵌入其中以便与演示技术无关。
根据第二条评论进行第二次编辑:
转换器是通过实现 IValueConverter
接口 ( MSDN : IValueConverter documentation ) 将值从一种类型转换为另一种类型的代码。它们需要在您的 XAML 中声明为资源,并在 Binding
.
中使用 StaticResource
指令进行引用
找到有关此内容(以及其他 WPF 基本主题)的优秀教程
我目前正在开发一个小型视频扑克应用程序,部分原因是它很有趣,而且我需要一个学校项目。
除非我遗漏了什么,否则我的逻辑应该完成,但是现在,当我将注意力转向应用程序的 UI 方面时,我遇到了障碍。
我 need/want 我的 ListView 要做的是:
- 不与用户执行的 mouseovers/mouse 次点击互动
- 通过代码填写,每次投注变化需要更换项目
- 当用户获胜时,通过更改背景在 ListView 中突出显示它 属性。
到目前为止我已经 "some" 成功了,这意味着我已经能够让它工作,这样我就可以 select 通过鼠标点击一个项目,然后颜色改变,但是我无法通过将 SelectedItem 更改为获胜手来使其工作。
我已经尝试了几乎所有我能想到的方法,但我已经走到了死胡同。 我相当确定它是通过绑定数据以某种方式实现的,但到目前为止我的所有努力都失败了。在数据绑定 XAML 元素方面,我仍然缺乏相当多的知识和经验。
如果这里有人可以帮助我 neat/clean/efficient 实现这一目标的方法,将不胜感激。
XAML:
<ListView x:Name="lvTest" HorizontalAlignment="Left" Height="200" VerticalAlignment="Top" Width="160" Margin="10,10,0,0">
<ListView.Resources>
<Style TargetType="GridViewColumnHeader">
<Setter Property="Visibility" Value="Collapsed" />
</Style>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<GridViewRowPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Width="105" DisplayMemberBinding="{Binding HandNaam}"/>
<GridViewColumn Width="45" DisplayMemberBinding="{Binding Betaling}"/>
</GridView>
</ListView.View>
</ListView>
C#:
List<Hand> hands = new List<Hand>();
//Bet has been changed, (re-)populate the ListView
void Betchanged()
{
hands.Clear();
lvTest.ItemsSource = null;
for (int i = 0; i <= 8; i++)
{
hands.Add(new Hand(Hand.hands[i], bet));
}
lvTest.ItemsSource = hands;
}
//Game ends
//After checking for a winning hand, highlight that hand in the ListView
private void EndGame()
{
//Do some stuff
//Check if there's a winning hand
int winnings;
Hand hand = null;
winnings = Poker.FindWin(splK, hands, out hand); //out hand is of type Hand
//If there's a winning hand, highlight it in the ListView
if (hand != null)
{
foreach (Hand h in lvTest.Items)
{
if (h.HandName == hand.HandName)
{
//This seems like the most logical (maybe not most efficient) way to find the correct item in the ListView
//Here's where the Background property for the ListViewItem should be changed
}
}
}
//Do some more stuff
}
PS:我的 XAML 中的当前模板样式覆盖了我的 ListViewItem 的 hover/click 交互。
编辑:这是一个屏幕截图,其中包含应更改 ListViewItem 的背景时的可能情况:
为了通过 Binding
通知控件其内容已更改,您的 ItemsSource
需要实施 INotifyCollectionChanged
。目前,实现此接口的最常见的泛型集合是 ObservableCollection<T>
.
hands
应该是 ObservableCollection<Hand>
而不是 List<Hand>
.
根据评论编辑:
WPF Binding
处理更改通知。对于属性,这意味着在需要通知其属性已更改的 class 上实施 INotifyPropertyChanged
。您的 Hand
class 应该在您要更改的特定值发生更改时实施 INotifyPropertyChanged
。
表示逻辑应由 View
class(或与 View
相关的代码(如 Converter
)处理,因此您应该绑定到您的模型 属性 值并使用转换器将其转换为 Brush
对象。
您可以只在模型对象上公开 Brush
,但这会破坏 MVVM 模式,因为 ViewModel
不应该具有 View-specific/presentation 技术 classes嵌入其中以便与演示技术无关。
根据第二条评论进行第二次编辑:
转换器是通过实现 IValueConverter
接口 ( MSDN : IValueConverter documentation ) 将值从一种类型转换为另一种类型的代码。它们需要在您的 XAML 中声明为资源,并在 Binding
.
StaticResource
指令进行引用
找到有关此内容(以及其他 WPF 基本主题)的优秀教程