【问题标题】:Finding the list of checked item in list of lists在列表列表中查找选中项目的列表
【发布时间】:2018-12-17 16:03:26
【问题描述】:

假设我有一个问卷应用程序,它由一个 ItemsControl 和一个控件列表组成,每个控件由一个 Label 和一个 ListBox 组成。每个 ListBox 中的项目是复选框或单选按钮等。

我的问题是:选中复选框时,我如何确定复选框适用于哪个问题?我应该在 Tag 属性中引用问题吗?如果是这样,我该怎么做?

下面的标签绑定代码不起作用。它绑定到 ListBoxItem。如何将其绑定到 ItemsControl 项?

MainWindow.xaml:

<Window x:Class="ListWithinListTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="450" Width="800">
  <Window.Resources>
    <ResourceDictionary>
      <Style x:Key="ConditionCheckBoxListStyle" TargetType="{x:Type ListBox}">
        <Setter Property="SelectionMode" Value="Multiple" />
        <Setter Property="ItemContainerStyle">
          <Setter.Value>
            <Style TargetType="{x:Type ListBoxItem}" >
              <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
              <Setter Property="Template">
                <Setter.Value>
                  <ControlTemplate TargetType="{x:Type ListBoxItem}">
                    <CheckBox IsChecked="{Binding IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}"
                              Click="CheckBoxClicked"
                              Tag="{Binding RelativeSource={RelativeSource TemplatedParent}}"
                              >
                      <ContentPresenter></ContentPresenter>
                    </CheckBox>
                  </ControlTemplate>
                </Setter.Value>
              </Setter>
            </Style>
          </Setter.Value>
        </Setter>
      </Style>
    </ResourceDictionary>
  </Window.Resources>

  <Grid>
    <ItemsControl Name="QuizControl" ItemsSource="{Binding QuizQuestions}" ScrollViewer.CanContentScroll="False">
      <ItemsControl.ItemTemplate>
        <DataTemplate>
          <StackPanel Margin="10 0 10 10" VerticalAlignment="Top">
            <Label Content="{Binding Text}" />
            <ListBox ItemsSource="{Binding Options}"
                     DisplayMemberPath="Text"
                     Tag="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl}}"
                     Style="{StaticResource ConditionCheckBoxListStyle}"
                     />
          </StackPanel>
        </DataTemplate>
      </ItemsControl.ItemTemplate>
    </ItemsControl>
  </Grid>
</Window>

MainWindow.xaml.cs:

using System.Windows;
using System.Windows.Controls;

namespace ListWithinListTest
{
    public class Option
    {
        public string Text { get; set; }
        public bool IsSelected { get; set; } = false;
    }

    public class Question
    {
        public string Text { get; set; }
        public Option[] Options { get; set; }
    }

    public class ViewModel
    {
        public Question[] QuizQuestions { get; set; }

        public ViewModel()
        {
            QuizQuestions = new Question[] {
                new Question { Text = "How are you?", Options = new Option[] { new Option { Text = "Good" }, new Option { Text = "Fine" } } },
                new Question { Text = "How's your dog?", Options = new Option[] { new Option { Text = "Sleepy" }, new Option { Text = "Hungry" } } },
            };
        }
    }

    public partial class MainWindow : Window
    {
        private ViewModel viewModel;

        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = viewModel = new ViewModel();
        }

        private void CheckBoxClicked(object sender, RoutedEventArgs e)
        {
            Question question = viewModel.QuizQuestions[???];
        }
    }
}

【问题讨论】:

    标签: wpf xaml


    【解决方案1】:

    好的,我把 Live Visual Tree 窗口弄乱了,直到通过消除过程,我意识到 ListBox 是问题将要绑定的对象。我现在知道这是一个很大的问题,但这就是我所在的地方。然后我使用RelativeSource AncestorType 找到它并使用DataSource 属性得到问题:

    MainWindow.xaml:

                    <CheckBox IsChecked="{Binding IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}"
                              Click="CheckBoxClicked"
                              Tag="{Binding RelativeSource={RelativeSource AncestorType=ListBox}}"
                              >
    

    MainWindow.xaml.cs:

        private void CheckBoxClicked(object sender, RoutedEventArgs e)
        {
            CheckBox checkBox = (CheckBox)sender;
            ListBox listBox = (ListBox)checkBox.Tag;
            Question question = (Question)listBox.DataContext;
            Debug.WriteLine(question.Text);
        }
    

    【讨论】:

      【解决方案2】:

      您已将 QuizQuestions 绑定到 QuizControl,您可以从 ItemsSource 属性中取回它。

      var  questions = (Question[]) QuizControl.ItemsSource;
      

      编辑

      看起来你自己得到了答案,这只是我想建议你原来问题的另一种方式:

      为您的 Option 类再创建一个属性

      public class Option
      {
          public string Text { get; set; }
          public bool IsSelected { get; set; } = false;
          public int Index{ get; set; }
      }
      

      然后将索引添加到您的每个问题选项中。

      QuizQuestions = new Question[] {
                  new Question { Text = "How are you?", Options = new Option[] { new Option { Text = "Good", Index = 0 }, new Option { Text = "Fine", Index = 0 } } },
                  new Question { Text = "How's your dog?", Options = new Option[] { new Option { Text = "Sleepy", Index = 1 }, new Option { Text = "Hungry", Index = 1 } } },
      };
      

      在您的 CheckBox 事件中,您可以获得选项索引

      private void CheckBoxClicked(object sender, RoutedEventArgs e)
      {
          var s = (CheckBox)sender;
          var op = (Option)s.Tag;
          Question question = viewModel.QuizQuestions[op.Index];
      }
      

      【讨论】:

      • 抱歉,我确实需要知道它来自的确切问题对象。我添加了一个编辑说我不需要它,但事实证明我确实需要它,所以我删除了它。对不起我的困惑。感谢您的回复!
      • 实际上,更好的方法是让您的 ViewModel 公开,然后您可以稍后在代码中从模型中检索 QuizQuestions 数组。
      • 我修复了代码,以便获得 ViewModel,但我仍然需要找到问题! :)
      猜你喜欢
      • 1970-01-01
      • 2014-10-13
      • 2014-08-10
      • 2023-02-11
      • 1970-01-01
      • 1970-01-01
      • 2022-11-21
      • 2013-11-17
      相关资源
      最近更新 更多