【问题标题】:Looping through WPF ListView DateTemplate Items循环遍历 WPF ListView DateTemplate 项
【发布时间】:2010-11-22 05:07:57
【问题描述】:

我在 Windows 窗体中有一个 ListView,我在创建窗体时绑定了一个对象列表。我想做的是在按钮单击循环中通过创建的项目并将其 IsEnabled 属性更改为 false。我尝试了两种方法,但都不是特别成功。任何人都可以帮助解决这些问题和/或建议一种替代方法吗?

我的 ListView XAML

<ListView Margin="6" Name="myListView" ItemsSource="{Binding Path=.}">
   <ListView.ItemTemplate>
      <DataTemplate>
         <Grid>
            <Grid.ColumnDefinitions>
               <ColumnDefinition Width="10"/>
               <ColumnDefinition Width="350"/>
               <ColumnDefinition Width="20"/>
               <ColumnDefinition Width="350"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
               <RowDefinition Height="30" />
               <RowDefinition Height="30" />
               <RowDefinition Height="30" />
            </Grid.RowDefinitions>
            <TextBlock Name="ItemNameTextBlock" Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="4" VerticalAlignment="Center" Text="{Binding Path=ItemName}" />
            <CheckBox Name="Action1CheckBox" Grid.Row="1" Grid.Column="1" Content="Action1" IsChecked="True" />
            <CheckBox Name="Action2CheckBox" Grid.Row="1" Grid.Column="3" Content="Action2" IsChecked="True" />
            <TextBox Height="23" Name="MyInputTextBox" Grid.Row="2" Grid.Column="1" Margin="2,0,2,0"  VerticalAlignment="Top" Width="25" Text="{Binding Path=DataValue}" />                                        
         </Grid>
      </DataTemplate>
   </ListView.ItemTemplate>
</ListView>

目标:按下按钮时(不相关的按钮)禁用复选框和文本框

尝试 1: 这不起作用,项目是数据绑定项目,我想不出一种方法来让控件本身做这样的事情。这甚至可能吗?

foreach (var item in ReleaseDeployProcessListView.Items)
{
   ((CheckBox)item.FindControl("Action1CheckBox")).IsEnabled = false;
}

尝试 2: 我在表单中添加了一个公共属性“IsFormElementsEnabled”,然后单击按钮将此值设置为 false。但我不知道如何/如果/我需要做什么来将其绑定到项目。我尝试了 IsEnabled="{Binding Path=IsFormElementsEnabled} (它不起作用,因为它绑定到对象并且不是那些对象的一部分)并且我尝试了 IsEnabled="{Binding Path=this.IsFormElementsEnabled} (它没有'似乎也不起作用)

【问题讨论】:

    标签: wpf winforms data-binding listview loops


    【解决方案1】:

    您总是可以在 ViewModel 上添加一个布尔值并将其绑定到您的 CheckBox?

    想象一下您的视图模型上的以下布尔值:

    public bool CanEdit 
    { 
        get 
        {
            return canEdit;
        }
        set 
        {
            canEdit = value;
            NotifyPropertyChanged("CanEdit");
        }
    }
    
    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(string info)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    } 
    

    另请注意,您的 ViewModel 必须实现 INotifyPropertyChanged 接口

    然后将此布尔值绑定到 DataTemplate 中的 CheckBox

    <CheckBox Name="Action1CheckBox" Grid.Row="1" Grid.Column="1" Content="Action1" IsChecked="True" IsEnabled="{Binding CanEdit}" />
    

    在你的 for 循环中,设置 CanEdit 的布尔值为 false:

    foreach (var item in ReleaseDeployProcessListView.Items)
    {
       item.CanEdit = false;
    }
    

    【讨论】:

    • 是的,这肯定会奏效,但我真的希望我能让其他两种机制之一发挥作用。
    • 查看我的新答案 ;) 虽然我仍然更喜欢这种方法 :)
    【解决方案2】:

    好的,这里是如何使您的两个解决方案都起作用;)

    尝试一:

    foreach (var item in ReleaseDeployProcessListView.Items)
    {
       ListViewItem i = (ListViewItem) ReleaseDeployProcessListView.ItemContainerGenerator.ContainerFromItem(item);
    
       //Seek out the ContentPresenter that actually presents our DataTemplate
       ContentPresenter contentPresenter = FindVisualChild<ContentPresenter>(i);
    
       CheckBox checkbox = (CheckBox)i.ContentTemplate.FindName("Action1CheckBox", contentPresenter);
       checkbox.IsEnabled = false;
    }
    
    
    private T FindVisualChild<T>(DependencyObject obj)
        where T : DependencyObject
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(obj, i);
            if (child != null && child is T)
                return (T)child;
        }
    
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(obj, i);
            T childOfChild = FindVisualChild<T>(child);
            if (childOfChild != null)
                return childOfChild;
        }
    
        return null;
    }
    

    尝试二:

    主控件上的依赖属性:

    public bool IsFormElementsEnabled
    {
        get { return (bool)GetValue(IsFormElementsEnabledProperty); }
        set { SetValue(IsFormElementsEnabledProperty, value); }
    }
    
    public static readonly DependencyProperty IsFormElementsEnabledProperty =
        DependencyProperty.Register("IsFormElementsEnabled", typeof(bool), typeof(YourClass), new PropertyMetadata(true));
    

    然后在 CheckBox 控件中使用 RelativeSource 绑定到您的主类:

    <CheckBox Name="Action1CheckBox" Grid.Row="1" Grid.Column="1" Content="Action1" IsChecked="True" 
              IsEnabled="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:YourControl}}, Path=IsFormElementsEnabled}" />
    

    您可以看到许多条通往罗马的道路;)不过,我更喜欢使用第一个选项,因为它可能是您业务逻辑的一部分,例如确定客户是否已经付款的布尔值或类似的东西: CustomerHasPaid

    希望对你有帮助

    【讨论】:

    • 非常感谢大角星,完美回答了我的问题。我同意另一个答案可能更好(并且我已将其标记为正确),但我很好奇如何完成其​​他两种方法。再次感谢!
    • 没问题..很高兴我能帮上忙 ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 2010-11-28
    • 2010-10-26
    • 1970-01-01
    • 2013-03-17
    相关资源
    最近更新 更多