gpt4 book ai didi

c# - 尝试在 View 之间共享项目时,SelectedItem 未正确更新

转载 作者:太空宇宙 更新时间:2023-11-03 10:21:21 26 4
gpt4 key购买 nike

我有一个场景,可以用不同的方式查看相同的项目集合。也就是说,我们对同一数据有多种视觉表示。为了保持我们的应用程序在视觉上干净,您一次只能查看其中一个 View 。我遇到的问题是,如果您在查看 View #1 时更改所选项目,那么当您切换到 View #2 时,所选项目不会正确更新。

我的复制步骤:

  • 在 View #1 上选择项目 #1。
  • 切换到 View #2 - 此时项目 #1 被选中
  • 向下滚动到“项目 #200”并选择它
  • 切换回 View #1
  • 项目 #1 仍将突出显示,如果您向下滚动到项目 #200,它也会突出显示

似乎当列表框折叠时,选择更改没有被拾取。我错过了什么?如果 UI 元素不可见,是否预计 PropertyChanged 事件不会更新它们?

下面是我的代码的一个非常简化的版本。基本上,我有一个绑定(bind)到两个不同 ListBox 控件的共享数组。

XAML:

<Window x:Class="SharedListBindingExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SharedListBindingExample"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListBox Grid.Row="0" x:Name="listBox1" ItemsSource="{Binding List1}">
<ListBox.Resources>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}"/>
</Style>

<DataTemplate DataType="{x:Type local:SharedListItem}">
<Grid HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Button Background="Red" />
<Label Grid.Row="1" Content="{Binding Name}" />
</Grid>
</DataTemplate>
</ListBox.Resources>


</ListBox>

<ListBox Grid.Row="0" x:Name="listBox2" ItemsSource="{Binding List2}" Background="AliceBlue" Visibility="Collapsed">
<ListBox.Resources>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}"/>
</Style>

<DataTemplate DataType="{x:Type local:SharedListItem}">
<Label Content="{Binding Name}" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"/>
</DataTemplate>
</ListBox.Resources>

</ListBox>

<Button Grid.Row="1" Click="Button_Click">Toggle View</Button>
</Grid>
</Window>

代码隐藏:

using System.Windows;

namespace SharedListBindingExample
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}

private void Button_Click(object sender, RoutedEventArgs e)
{
if (listBox1.Visibility == Visibility.Collapsed)
{
listBox1.Visibility = Visibility.Visible;
listBox2.Visibility = Visibility.Collapsed;
}
else
{
listBox2.Visibility = Visibility.Visible;
listBox1.Visibility = Visibility.Collapsed;
}
}
}
}

View 模型:

using System.Collections.Generic;

namespace SharedListBindingExample
{
public class TwoPropertiesForSameListViewModel
{
private readonly List<SharedListItem> _sharedList;

public TwoPropertiesForSameListViewModel()
{
_sharedList = new List<SharedListItem>();

for (int i = 0; i < 300; i++)
{
_sharedList.Add(new SharedListItem($"Item #{i}"));
}
}

public IEnumerable<SharedListItem> List1
{
get
{
return _sharedList;
}
}

public IEnumerable<SharedListItem> List2
{
get
{
return _sharedList;
}
}
}
}

共享列表项:

using System.ComponentModel;

namespace SharedListBindingExample
{
public class SharedListItem : INotifyPropertyChanged
{
private bool _isSelected;

public SharedListItem(string name)
{
Name = name;
}

public string Name { get; set; }

public bool IsSelected
{
get
{
return _isSelected;
}

set
{
if (value != _isSelected)
{
_isSelected = value;

OnPropertyChanged("IsSelected");
}
}
}

public event PropertyChangedEventHandler PropertyChanged;

private void OnPropertyChanged(string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

最佳答案

我相信您需要在两个不同的 View 之间使用一个 CollectionViewSource 对象来使所选项目保持同步。我在自己的应用程序中做了类似的事情。

我有一个控件,它在 Xaml 中定义了一个 CollectionViewSource 资源:

<UserControl.Resources>
<CollectionViewSource x:Key="DataView" />
</UserControlResources>

该控件还有一个用于 CollectionViewSourceDependencyProperty,允许它数据绑定(bind)到其他控件:

public static readonly DataViewProperty =
DependencyProperty.Register( "DataView", typeof( CollectionViewSource ), typeof( YourControlType ), new PropertyMetadata( null ) );

public CollectionViewSource DataView {
get { return (CollectionViewSource) GetProperty( DataViewProperty); }
set { SetProperty( DataViewProperty, value );
}

然后在组件构造函数中,在调用InitializeComponent 之后,您必须执行如下代码:

public MyUserControl() {
InitializeComponent();

DataView = FindResource( "DataView" ) as CollectionViewSource;
DataView.Source = YourObservableCollection;
}

在您想要共享此对象的其他 View 中,您创建一个新的 CollectionViewSource DependencyProperty。这允许您在具有不同数据 View 的窗口中将两个属性相互绑定(bind)。在我的第二个控件中,我有另一个 ObservableCollection 对象属性,但它没有在控件的构造函数中初始化。我所做的是在控件的 Loaded 事件处理程序中,我将 ObservableCollection 属性的值设置为 CollectionViewSource 对象的 Source 属性的值。即:

if ( DataCollection == null && DataView != null ) {
DataCollection = (ObservableCollection<DataType>) DataView.Source;
DataGrid.ItemsSource = DataView.View;
}

在此之后,两个控件共享相同的 ObservableCollection 和相同的 CollectionViewSourceCollectionViewSource 使两个控件的选定项保持同步。

显然,您可以根据需要在多个 View 之间共享该 CollectionViewSource 对象。一个控件必须声明该对象,其他控件必须共享它。

关于c# - 尝试在 View 之间共享项目时,SelectedItem 未正确更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33373189/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com