繁体   English   中英

将CheckBox IsChecked属性绑定到ListView的SelectedItems属性

[英]Binding the CheckBox IsChecked Property to SelectedItems Property of a ListView

我在MVVM数据绑定方面遇到困难。

在我的示例中,我有一个ListView ,其中填充了包含CheckBox和其他一些内容的项目。

<ListView 
   Background="#f0f0f0" 
   Grid.Row="1" 
   ItemsSource="{Binding ListViewCollection}" 
   SelectedItem="{Binding SelectedItem}" 
   IsSynchronizedWithCurrentItem="True" 
   BorderThickness="0" 
   Margin="5">
   <ListView.View>
      <GridView>
         <GridView.Columns>
            <GridViewColumn>
               <GridViewColumn.CellTemplate>
                  <DataTemplate>
                     <CheckBox  Tag="{Binding TheValue}" IsChecked="{Binding IsChecked}" />
                  </DataTemplate>
               </GridViewColumn.CellTemplate>
            </GridViewColumn>
            <GridViewColumn DisplayMemberBinding="{Binding TheText}" Header="#Cell" />
            <GridViewColumn DisplayMemberBinding="{Binding TheVoltage}" Header="U[V]" />
         </GridView.Columns>
      </GridView>
   </ListView.View>
</ListView>

ItemSourceItemSource中一样, ListViewItemSource绑定到ViewModel中数据类的ObservableCollection

现在,我想将每个列表视图项目的Checkbox.IsChecked属性连接到父级ListView.SelectedItems属性以触发它。 为什么? 因为我想显示/隐藏一系列数据图。 因此,如果选中了第一行中的CheckBox ,则显示图形1。如果未选中第二行中的CheckBox ,则隐藏图形2,依此类推。 像这样:

public ListViewItem SelectedItem
    {
        get { return mSelectedItem; }
        set
        {
            if (mSelectedItem!= value)
            {
                mSelectedItem= value;
                RaisePropertyChanged("SelectedItem");
                if (SelectedItem.IsChecked == true)
                {
                    OxyplotModel.Series[1].IsVisible = false;
                    OxyplotModel.InvalidatePlot(true);
                }
            }
        }
    }

要触发此属性,您必须在GUI中单击两次。 首先选中CheckBox ,然后再次单击该行以触发并隐藏图形。 但是我想在单击CheckBox之后立即触发SelectedItems属性。

现在,我将命令绑定到CheckBox并传递一个参数来区分复选框。 但是正如我所说,我想使用该属性。

这有可能还是有更好的想法来解决我的问题?

所选项目将是绑定到“项目”源的“项目”的类型。 如果项目来源为列表,则表示所选项目为学生。

据我了解您的问题,这是由CheckBoxListViewItem窃取焦点引起的。 如果要在单击CheckBox时选择项目,则可以使用动画触发,只要ListViewItem某项获得焦点,它将设置IsSelected为true

<ListView ... 
   ItemsSource="{Binding ListViewCollection}" 
   SelectedItem="{Binding SelectedItem}" 
   SelectionMode="Single">
   <ListView.View>
       <!-- removed -->
   </ListView.View>
   <ListView.ItemContainerStyle>
      <Style TargetType="{x:Type ListViewItem}">
         <Style.Triggers>
            <EventTrigger RoutedEvent="GotKeyboardFocus">
               <BeginStoryboard>
                  <Storyboard>
                     <BooleanAnimationUsingKeyFrames BeginTime="0:0:0" Duration="0:0:0" Storyboard.TargetProperty="IsSelected">
                        <DiscreteBooleanKeyFrame Value="True" />
                     </BooleanAnimationUsingKeyFrames>
                  </Storyboard>
               </BeginStoryboard>
            </EventTrigger>
         </Style.Triggers>
      </Style>
   </ListView.ItemContainerStyle>
</ListView>

您还需要指定SelectionMode="Single"否则不会取消选择上一个项目

编辑

它将新的事件触发器添加到项目容器样式( ListViewItem ),只要发生GotKeyboardFocus事件,该触发器就会执行。 这是冒泡事件,表示它将从任何ListViewItem子项中冒出可视树,并最终到达ListViewItem ,在此它将触发BooleanAnimationUsingKeyFrames动画,该动画能够更改Boolean属性的Boolean 在这种情况下,它并不是真正的动画,因为它花费了0秒,但是会将IsSelected属性(由Storyboard.TargetProperty指定)设置为true

我想发布一种替代方法,以使用Command和CommandParameter实现此解决方案。

在您的XAML中,将命令绑定到复选框。 还要将CommandParameter绑定到一个值,该值将传递给Command本身。 请注意:由于ListView的ItemSource设置为Observablecollection,因此必须使用以下命令更改为父DataContext

Command =“ {Binding ElementName = NameOfListView,Path = DataContext.NameOfCommand}”

从ViewModel DataContext绑定命令。 您也可以使用Ancestor来获取父数据上下文。

<ListView
   Background="#f0f0f0" 
   Grid.Row="1" 
   ItemsSource="{Binding ListViewCollection}" 
   Name="ListView" 
   IsSynchronizedWithCurrentItem="True" 
   BorderThickness="0" 
   Margin="5">
   <ListView.View>
      <GridView>
         <GridView.Columns>
            <GridViewColumn>
               <GridViewColumn.CellTemplate>
                  <DataTemplate>
                      <CheckBox IsChecked="{Binding IsChecked}" 
                      Command="{Binding ElementName=ListView,Path=DataContext.HideShowGraph}" 
                      CommandParameter="{Binding TheValue, Mode=OneWay}" />
                  </DataTemplate>
               </GridViewColumn.CellTemplate>
            </GridViewColumn>
            <GridViewColumn DisplayMemberBinding="{Binding TheText}" Header="#Cell" />
            <GridViewColumn DisplayMemberBinding="{Binding TheVoltage}" Header="U[V]" />
         </GridView.Columns>
      </GridView>
   </ListView.View>
</ListView>

然后在您的ViewModel中,声明一个带有参数的RelayCommand和相应的委托方法。

public class ViewModel : ViewModelBase
    {
        public ViewModel()
        {
            HideShowGraph = new RelayCommand<int>(foo => HideShowGraphExecute(foo));
        }

        public ICommand HideShowGraph { get; private set; }

        private void HideShowGraphExecute(int foo)
        {
           //...evaluate foo
        }
    }

因此,如果选中了ListView中的一个Checkbox,则将调用Command并将CommandParameter的有界值(在本示例中为“ TheValue”)传递给委托方法HideShowGraphExecute。 使用此值,您可以区分复选框。

希望它也有帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM