【问题标题】:How to handle when Items Control element has changed? WPF, C#当 Items Control 元素发生变化时如何处理? WPF, C#
【发布时间】:2020-05-09 17:48:07
【问题描述】:
下面我有一个带有城市的ListView,当检查城市时,第二个列表(与人员)必须仅显示该城市的人。
<ListView ItemsSource="{Binding Cities}">
     <ListView.ItemTemplate >
          <DataTemplate>
               <StackPanel>
                    <Label Content="{Binding Name}" />
                    <CheckBox IsChecked="{Bidning IsChecked}" />
               </StackPanel>
          </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

还有第二个人员列表视图:

<ListView ItemsSource="{Binding Persons}">
     <ListView.ItemTemplate >
          <DataTemplate>
               <StackPanel>
                    <Label Content="{Binding Name}" />
                    <Label Content="{Bidning Surname}" />
               </StackPanel>
          </DataTemplate>
     </ListView.ItemTemplate>
</ListView>

您可以在下面看到带有与 ListViews 绑定的列表的视图模型。

    public ListCollectionView Cities
    {
        get { return _cities; }
        set
        {
            _cities = value;
            RaisePropertyChanged();
        }
    }

    public ListCollectionView Persons
    {
            get { return _persons; }
            set
            {
                _persons= value;
                RaisePropertyChanged();
            }
     }

问题是当用户选中 Cities ListView 内的复选框时如何处理,以便我可以刷新 Persons 列表并仅从选中的 City 返回 Persons?我不知道在View Model中应该写什么,所以当ListView children属性发生变化时我不知道如何处理。

【问题讨论】:

  • 您可以管理选定的城市并在人员列表发生变化时更新它
  • 请注意,Cities 和 Persons 集合的类型不应是 ListCollectionView,而是 List&lt;T&gt; 或 ObservableCollection&lt;T&gt;,其中 T 是 City 或 Person。
  • 如果一个给定的人与一个特定的城市相关联,那么我希望一个城市有一个可观察的 Person 集合作为它的属性之一。然后,您可以将人员列表视图的 itemssource 绑定到 selectedCity.People。从 City 项目模板中删除复选框,并使用 City 的选择来驱动对哪个城市的人感兴趣。您还需要绑定选定的城市项目或将人员列表视图绑定到选定项目。城市列表视图的人员。

标签: c# wpf listview binding viewmodel


【解决方案1】:

您必须将public City SelectedCity 属性添加到视图模型并在视图中绑定选定的城市值

<ListView ItemsSource="{Binding Cities}" SelectedItem="{Binding SelectedCity">

在 SelectedCity 设置器中,您可以像这样更新 Persons 集合

class PersonsByCitiesViewModel
{
public City SelectedCity
{
get{}
set
{
  Persons = LoadPersons(value);
}
}

public ListCollectionView LoadPersons(City selected)
{
  var persons = LoadAll();
  if (selected != null)
    persons = persons.Where(_ => _.CityId = selected.CityId);
  return new ListCollectionView(persons);
}
}

【讨论】:

  • 当我从列表中选择一个孩子时它会起作用,但我希望能够选择多个孩子(选中多个复选框)解决方案是在 City 类中重建属性 IsChecked:公共布尔 IsChecked { 获取 => _isChecked;设置 { _isChecked = 值; OnPropertyChanged(); }
  • 但是在 City 类中,即使我可以在选中复选框时处理我也无法访问 Person Collection,因为我在 City 类中......所以我仍然不知道该怎么做跨度>
  • 您可以在PersonsByCitiesViewModel.LoadPersons 方法中检查新的City.Selected 属性(或将选定城市列表放入加载器类)。然而,当用户点击城市复选框时,必须使用一些魔法来过滤人员。你可以尝试实现它2. Two way binding answer。或者您可以添加 LoadPersons 按钮供用户使用来启动加载人员流程
【解决方案2】:

处理 SelectedItem 很好,但前提是我只想从列表中选择一个城市。 如果我想选择多个怎么办?

我尝试在 Cities 类中处理 IsChecked 属性,但在 Cities 类中,我无法访问视图模型中的其他元素,这些元素位于城市列表和人员列表所在的视图模型中。

【讨论】:

    【解决方案3】:

    我建议处理 CheckBox 元素的 Checked 和 Unchecked 事件。

    查看:

    <ListView ItemsSource="{Binding Cities}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <Label Content="{Binding CityName}" />
                    <CheckBox IsChecked="{Binding IsChecked}">
                         <i:Interaction.Triggers>
                             <i:EventTrigger EventName="Checked">
                                 <i:InvokeCommandAction Command="{Binding DataContext.SelectedCitiesChangedCommand, RelativeSource={RelativeSource AncestorType=ListView}}"/>
                             </i:EventTrigger>
                             <i:EventTrigger EventName="Unchecked">
                                 <i:InvokeCommandAction Command="{Binding DataContext.SelectedCitiesChangedCommand, RelativeSource={RelativeSource AncestorType=ListView}}"/>
                             </i:EventTrigger>
                         </i:Interaction.Triggers>
                    </CheckBox>
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    
    <ListView ItemsSource="{Binding ShownPeople}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <Label Content="{Binding Name}" />
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    

    视图模型:

    public List<City> Cities { get; } = new List<City>();
    
    public List<Person> Persons { get; } = new List<Person>();
    
    public ObservableCollection<Person> ShownPeople { get; } = new ObservableCollection<Person>();
    
    
    public ICommand SelectedCitiesChangedCommand { get; }
    
    
    public ViewModel()
    {
        SelectedCitiesChangedCommand = new DelegateCommand(SelectedCitiesChanged);
    }
    
    
    private void SelectedCitiesChanged()
    {
        var checkedCities = Cities.Where(city => city.IsChecked);
    
        ShownPeople.Clear();
        ShownPeople.AddRange(Persons.Where(person => checkedCities.Any(city => city.CityName == person.City)));
    }
    

    【讨论】:

      猜你喜欢
      • 2013-11-04
      • 1970-01-01
      • 1970-01-01
      • 2013-02-22
      • 1970-01-01
      • 2013-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多