简体   繁体   English

使用可观察的集合和数据模板的ListBox中的C#WPF单选按钮

[英]C# WPF Radio Buttons in ListBox using observable collection and Data Template

I am making a program using similar structure as Data Binding Demo ( http://code.msdn.microsoft.com/Data-Binding-Demo-82a17c83 ). 我正在使用与数据绑定演示( http://code.msdn.microsoft.com/Data-Binding-Demo-82a17c83 )类似的结构制作程序。

I am right now trying to implement radio buttons inside my list box data template. 我现在正在尝试在列表框数据模板中实现单选按钮。 My aim is to modify the 'selected' value of the proper Question object. 我的目的是修改适当的Question对象的“选定”值。 I guess it is possible by giving the proper Binding to 'Checked' property of the 2 RadioButton elements in my template but so far I have not been able to do that. 我想可以通过对模板中2个RadioButton元素的“ Checked”属性进行适当的绑定来实现,但是到目前为止,我还没有做到这一点。 My other attempt was to do this in code behind but I also failed here. 我的另一尝试是在后面的代码中执行此操作,但我在这里也失败了。 Thank you for any advise. 感谢您的任何建议。

Question class 问题类别


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using System.ComponentModel;


namespace WpfApplication1
{
    public class Question : INotifyPropertyChanged
    {
        private int ID;
        private int question_number;
        private string question;
        private bool is_private;
        private bool selected;

        public event PropertyChangedEventHandler PropertyChanged;

        public int _ID
        {
            get { return this.ID; }
            set { this.ID = value; OnPropertyChanged("_ID"); }
        }

        public int _question_number
        {
            get { return this.question_number; }
            set { this.question_number = value; OnPropertyChanged("_question_number"); }
        }

        public string _question
        {
            get { return this.question; }
            set { this.question = value; OnPropertyChanged("_question"); }
        }

        public bool _is_private
        {
            get { return this.is_private; }
            set { this.is_private = value; OnPropertyChanged("_is_private"); }
        }

        public bool _selected
        {
            get { return this.selected; }
            set { this.selected = value; OnPropertyChanged("_selected"); }
        }

        public Question(int ID, int question_number, string question, bool is_private, bool selected)
        {
            this.ID = ID;
            this.question = question;
            this.question_number = question_number;
            this.is_private = is_private;
            this.selected = selected;
        }

        protected void OnPropertyChanged(string property)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
        }
    }
}

xaml file XAML文件

<Window x:Class="WpfApplication1.Audyt_window"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Audyt" 
        xmlns:src="clr-namespace:WpfApplication1" 
        ResizeMode="NoResize"
        SizeToContent="WidthAndHeight"
        WindowStartupLocation="CenterScreen"
        >

    <Window.Resources>

        <CollectionViewSource Source="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}, Path=Questions}" x:Key="questions_collection" />

        <Style x:Key="text_style" TargetType="TextBlock">
            <Setter Property="Foreground" Value="#333333" />
        </Style>

        <DataTemplate x:Key="Questions_Template" DataType="{x:Type src:Question}">
            <Border BorderThickness="2" BorderBrush="Brown" Padding="7" Name="Question_List_Border" Margin="3" Width="365">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="20"/>
                        <ColumnDefinition Width="30"/>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="60"/>
                        <ColumnDefinition Width="60"/>
                    </Grid.ColumnDefinitions>

                    <TextBlock Grid.Row="0" Grid.Column="0"
                               Name="textblock_ID"
                               Style="{StaticResource text_style}"
                               Text="ID: "
                               >
                    </TextBlock>
                    <TextBlock Grid.Row="0" Grid.Column="1"
                               Name="textblock2_ID"
                               Style="{StaticResource text_style}"
                               Text="{Binding Path=_ID}"
                               >
                    </TextBlock>
                    <TextBlock Grid.Row="1" Grid.Column="0"
                               Name="textblock_question_number"
                               Style="{StaticResource text_style}"
                               Text="Val"
                               >
                    </TextBlock>
                    <TextBlock Grid.Row="1" Grid.Column="1"
                               Name="textblock2_question_number"
                               Style="{StaticResource text_style}"
                               Text="{Binding Path=_question_number}"
                               >
                    </TextBlock>
                    <TextBlock Grid.Row="0" Grid.Column="2" Grid.RowSpan="3" TextWrapping="Wrap"
                               Name="textblock_question"
                               Style="{StaticResource text_style}"
                               Text="{Binding Path=_question}"
                               >
                    </TextBlock>
                    <RadioButton GroupName="{Binding Path=_ID}" Grid.Row="0" Grid.Column="3" HorizontalAlignment="Center" VerticalAlignment="Center" Checked="RadioButtons_Yes" Margin="10,17,11,17">Tak</RadioButton>
                    <RadioButton GroupName="{Binding Path=_ID}" Grid.Row="0" Grid.Column="4" HorizontalAlignment="Center" VerticalAlignment="Center" Checked="RadioButtons_No" Margin="10,17,11,17">Nie</RadioButton>
                </Grid>
            </Border>
        </DataTemplate>

    </Window.Resources>

    <Border Padding="10">
        <Grid>

            <ListBox Name="Questions_View_List" HorizontalAlignment="Left" VerticalAlignment="Top" 
                 Height="525" Width="400" Margin="0,0,0,0" BorderThickness="2" BorderBrush="DimGray"
                 ItemsSource="{Binding Source={StaticResource questions_collection}}"  
                 ItemTemplate="{StaticResource Questions_Template}"
                 SelectionMode="Single"
                 SelectedValue="{Binding Path=_ID}" 
                 SelectedValuePath="{Binding Path=_ID}"
                 SelectionChanged="Questions_View_List_SelectionChanged"
                 >
            </ListBox>


        </Grid>
    </Border>
</Window>

code behind 背后的代码

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.ComponentModel;


namespace WpfApplication1
{
    public partial class Audyt_window : Window
    {       
        CollectionViewSource questions_collection;

        private ObservableCollection<Question> questions = new ObservableCollection<Question>();
        public ObservableCollection<Question> Questions
        {
            get { return this.questions; }
            set { this.questions = value; }
        }

        public Audyt_window()
        {
            DataContext = this;  
            load_temp_data();
            InitializeComponent();
            questions_collection = (CollectionViewSource)(this.Resources["questions_collection"]);
        }

        private void load_temp_data()
        {
            Question que1 = new Question(1, 2, "Question1", false, false);
            Question que2 = new Question(2, 1, "Question2", false, false);
            Question que3 = new Question(3, 0, "Question3", false, false);
            this.Questions.Add(que1);
            this.Questions.Add(que2);
            this.Questions.Add(que3);
        }

        private void Questions_View_List_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
           // Question question_temp = (Question)((ListBox)e.Source).SelectedValue;

        }

        private void RadioButtons_Yes(object sender, RoutedEventArgs e)
        {
            //Question question_temp = (Question)((ListBox)e.Source(RadioButton)e.Source; // Can't really figure this out ;/ 
            //Variables.selected_question = question_temp._ID;


        }

        private void RadioButtons_No(object sender, RoutedEventArgs e)
        {


        }

    }
}

While your question is still a little unclear because you have only used a few lines of words compared with your million lines of code, I believe that I know what you are after. 尽管您的问题仍然不太清楚,因为与数百万行代码相比,您仅使用了几行单词,但我相信我知道您的要求。 I think that you will need to create an enum to differentiate between the different answers to your questions... perhaps something as simple as this?: 我认为您将需要创建一个enum来区分问题的不同答案……也许就这么简单?

public enum Answer { A, B, C, D ... }

Now that you have an enum , you can use that on the different RadioButton s, along with an EnumToBoolConverter : 现在您有了一个enum ,可以将其与EnumToBoolConverter一起用于不同的RadioButton

<StackPanel>
    <RadioButton IsChecked="{Binding AnswerProperty, Converter={StaticResource 
        EnumToBoolConverter}, ConverterParameter=A}" Content="Answer A" />
    <RadioButton IsChecked="{Binding AnswerProperty, Converter={StaticResource 
        EnumToBoolConverter}, ConverterParameter=B}" Content="Answer B" />
    <RadioButton IsChecked="{Binding AnswerProperty, Converter={StaticResource 
        EnumToBoolConverter}, ConverterParameter=C}" Content="Answer C" />
    <RadioButton IsChecked="{Binding AnswerProperty, Converter={StaticResource 
        EnumToBoolConverter}, ConverterParameter=D}" Content="Answer D" />
</StackPanel>

The AnswerProperty here relates to your 'selected' value of the proper Question object as you called it. 这里的AnswerProperty与您所调用的相应Question对象的“选定”值有关 Of course, you'll need to change that property type to the type of your enum now. 当然,您现在需要将该属性类型更改为您的enum类型。 You can find many different versions of the EnumToBoolConverter online and there is one in the answer to the How to bind RadioButtons to an enum? 您可以在线找到许多不同版本的EnumToBoolConverter并且在如何将RadioButtons绑定到枚举的答案中有一个。 question here on Stack Overflow. 在堆栈溢出问题。

Try this , As you want to change the Question Object on selection of Radio 尝试此操作,因为要在选择广播时更改问题对象

        <RadioButton Command="{Binding RadioCommand}" CommandParameter="Tak" GroupName="MyRadioGroup">Tak</RadioButton>
    <RadioButton Command="{Binding RadioCommand}" CommandParameter="Nie"  GroupName="MyRadioGroup">Nie</RadioButton>

Question.cs Question.cs

    public class Question : INotifyPropertyChanged
{
   //your existing code
    //....
    //.....
    //Add Command to your Question class as below

    MyCommand radioCommand;
    public MyCommand RadioCommand
    {
        get { return radioCommand ?? (radioCommand = new MyCommand(OnRadioCommand, () => true)); } 
    }

    void OnRadioCommand(object obj)
    {
        if (obj != null)
        {
            var checkedRadiochecked = obj.ToString();
            //checkedRadiochecked  will have either Tak or Nie according to 
            //  RadioButton checked
            //do your stuff of changing this object here
        }
    }
}

} }

Mycommand or you can use other like Relaycommand Mycommand或您可以使用其他类似Relaycommand的命令

    public class MyCommand : ICommand
{

    Action<object> executeAction;
    Func<bool> canExecute;

    public MyCommand(Action<object> executeAction, Func<bool> canExecute)
    {
        this.executeAction = executeAction;
        this.canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        if (canExecute != null)
            return canExecute();
        else
            return true;
    }

    public void RaiseCanExecuteChanged()
    {
        if (CanExecuteChanged != null)  
            CanExecuteChanged(this, new EventArgs());
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        if (executeAction != null)
            executeAction(parameter);
    }
}

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

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