【问题标题】:Listbox with selectable checkboxes带有可选复选框的列表框
【发布时间】:2014-03-04 09:21:14
【问题描述】:

我正在尝试达到这种情况:

  • 拥有一个 ListBox,每个单元格都包含一个 CheckBox 和一个 TextBox,通过 DataTemplate
  • 使列表可选择,即。我可以将 SelectedItems 绑定到我的 VM 中的集合。
  • 将这些选择链接到复选框的状态(选中、未选中)。
  • 每当用户在TextBox中输入内容时,Checkbox就会被选中并被选中,反之亦然,当字符串为空时,它将被取消选中。

我设法像这样分别获得所有这些标准:

  • 使用此 solution 绑定到 SelectedItems。
  • 将 CheckBox.IsChecked 绑定到:
    <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}" Path="IsSelected" Mode="OneWayToSource"/>
  • 将 CheckBox.IsChecked 绑定到:
    <Binding Path="Text" ElementName="MyTextBox" Converter="{View:EmptyStringToBooleanConverter}" Mode="OneWay"/>

问题是我无法让这两个绑定一起工作。我尝试过其他解决方案,例如 DataTriggers,但它们没有帮助,因为 IsSelected 不可访问,而且我需要绑定到 DataTemplate 中的某些内容。
我真的想避免必须向我的类添加属性“IsSelected”(由 DataTemplate 表示)。

请帮忙,只要他们是 MVVM-y,我愿意听到疯狂的建议。 谢谢!

【问题讨论】:

    标签: c# wpf xaml


    【解决方案1】:

    一般:

    • 复选框默认未选中
    • 当您键入字符串“checked”时,复选框将被选中,否则将保持未选中状态

    希望对你有帮助。

    XAML

    <Window x:Class="MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:clr="clr-namespace:WpfApplication1"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <Grid.Resources>
                <clr:StringToBooleanConverter x:Key="StringToBooleanConverter"/>
            </Grid.Resources>
            <ListBox ItemsSource="{Binding}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <CheckBox x:Name="chb" IsChecked="{Binding Text, ElementName=txt, Mode=OneWay, Converter={StaticResource StringToBooleanConverter}}"/>
                            <TextBox x:Name="txt" Text="{Binding Title, UpdateSourceTrigger=PropertyChanged}" Width="150"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </Grid>
    </Window>
    

    代码隐藏

    Imports System.Collections.ObjectModel
    
    Class MainWindow
        Public Sub New()
            InitializeComponent()
            Me.DataContext = New ObservableCollection(Of DummyClass)(Enumerable.Range(0, 10).Select(Function(a) New DummyClass() With {.Title = "Dummy Title: " & a}))
        End Sub
    End Class
    
    Public Class DummyClass
        Property Title As String
    End Class
    
    Public Class StringToBooleanConverter
        Implements IValueConverter
    
        Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.Convert
            Dim strValue = System.Convert.ToString(value)
            If String.IsNullOrEmpty(strValue) Then
                Return False 'Unchecked
            End If
    
            If strValue = "checked" Then
                Return True 'checked
            End If
    
            Return False 'default
        End Function
    
        Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack
            Throw New NotImplementedException()
        End Function
    End Class
    

    【讨论】:

      【解决方案2】:

      这是 XAML 代码:

               <ListBox ItemsSource="{Binding MyList}" SelectionMode="Multiple" Width="200">
                  <ListBox.ItemTemplate>
                      <DataTemplate>
                          <DockPanel Margin="2">
                              <CheckBox DockPanel.Dock="Left" IsChecked="{Binding IsSelected}"/>
                              <TextBox Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}" Background="Transparent"/>
                          </DockPanel>
                      </DataTemplate>
                  </ListBox.ItemTemplate>
                  <ListBox.ItemContainerStyle>
                      <Style TargetType="{x:Type ListBoxItem}">
                          <Setter Property="IsSelected" Value="{Binding IsSelected}"/>
                      </Style>
                  </ListBox.ItemContainerStyle>
              </ListBox>
      

      及其背后的代码:

      public partial class MainWindow : Window
      {
          public MainWindow()
          {
              InitializeComponent();
              DataContext = this;
              for (int i = 0; i < 100; i++)
              {
                  MyList.Add(new ViewModel());
              }
          }
          //MyList Observable Collection
          public ObservableCollection<ViewModel> MyList { get { return _myList; } }
          private ObservableCollection<ViewModel> _myList = new ObservableCollection<ViewModel>();
      }
      

      ViewModel 类(每个项目):

      public class ViewModel : DependencyObject
      {
          //Text Dependency Property
          public string Text
          {
              get { return (string)GetValue(TextProperty); }
              set { SetValue(TextProperty, value); }
          }
          public static readonly DependencyProperty TextProperty =
              DependencyProperty.Register("Text", typeof(string), typeof(ViewModel),
              new UIPropertyMetadata(null, (d, e) =>
              {
                  ((ViewModel)d).IsSelected = !string.IsNullOrWhiteSpace((string)e.NewValue);
              }));
          //IsSelected Dependency Property
          public bool IsSelected
          {
              get { return (bool)GetValue(IsSelectedProperty); }
              set { SetValue(IsSelectedProperty, value); }
          }
          public static readonly DependencyProperty IsSelectedProperty =
              DependencyProperty.Register("IsSelected", typeof(bool), typeof(ViewModel),
              new UIPropertyMetadata(false, (d, e) =>
              {
      
              }));
      }
      

      【讨论】:

      • 这对我不利,有几个原因。 A)我试图在我的对象中避免一个名为“IsSelected”的属性。 B)我希望 CheckBox 进行选择的原因不是因为它的背景颜色很漂亮,而是因为我希望它成为“SelectedItems”的实际部分。
      • 在这种情况下,我的头顶上有一些东西可以提供帮助。 ListBox(或其他可选控件)中的项目具有 Selector.IsSelected。但我不记得它的正确用法。也许在 ListBox.ItemContainerStyle 中?
      • 考虑过了,但 Style 无法访问 DataTemplate 中的 TextBox 或 CheckBox。
      • 我想这更好,但它仍然包括添加的“IsSelected”属性。有关全部要求,请参阅我的原始帖子。
      • 我使用标签(在 DockPanel 中)和 DataTrigger.ExitAction 进行了测试,但观察到了不可预测的行为。我认为这是因为使用 string.IsNullOrEmpty 是正确的做法。
      猜你喜欢
      • 1970-01-01
      • 2018-06-01
      • 2014-04-11
      • 1970-01-01
      • 2012-03-09
      • 1970-01-01
      • 2018-02-14
      • 2011-05-26
      • 1970-01-01
      相关资源
      最近更新 更多