将集合对象绑定到xaml中的按钮而不使用后面的代码

时间:2018-03-14 17:22:14

标签: c# wpf mvvm

我有一份问卷调查申请表,我希望一次一个地显示对象(问题+我的案例中的答案)。这意味着我希望用户显示第一个问题,回答它,然后单击按钮并获得第二个问题(在同一窗口中),单击另一个按钮/或相同的按钮并获得第三个问题,依此类推。目前,我很难通过仅使用XAML将第二个问题绑定到我的按钮。是否可以在不使用代码的情况下执行此操作?如果是这样,请给我一个想法。谢谢你的期待。

这是我的ViewModel:

namespace TestAppMVVM.ViewModel
{
    public class TestViewModel
    {
        public ObservableCollection<Test> BeginnerTests
        {
            get;
            set;
        }

        public Test CurrentQuestion
        {
            get;
            set;
        }

        public Test NextQuestion
        {
            get;
            set;
        }

        public Test CurrentAnswer
        {
            get;
            set;
        }

        public Test NextAnswer
        {
            get;
            set;
        }




        public void LoadBeginner()
        {
            ObservableCollection<Test> tests = new ObservableCollection<Test>();

            tests.Add(new Test { Index = 1, Question = "1.What is the capital of England ?", FirstAnswer = "Paris", SecondAnswer = "London", ThirdAnswer = "Berlin" });
            tests.Add(new Test { Index = 2, Question = "2.What is the capital of France ?", FirstAnswer = "Paris", SecondAnswer = "London", ThirdAnswer = "Berlin" });
            tests.Add(new Test { Index = 3, Question = "3.What is the capital of Germany ?", FirstAnswer = "Paris", SecondAnswer = "London", ThirdAnswer = "Berlin" });


            BeginnerTests = tests;
            CurrentQuestion = BeginnerTests[0];
            CurrentAnswer = BeginnerTests[0];

            NextQuestion = BeginnerTests[1];
            NextAnswer = BeginnerTests[1];

        }
    }
}   

在这里我粘贴了视图:

<Grid Background="Yellow">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="20"/>
        <ColumnDefinition Width="auto"/>
        <ColumnDefinition Width="auto"/>
        <ColumnDefinition Width="auto"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="20"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height ="20"/>
        <RowDefinition Height ="100"/>
        <RowDefinition Height ="auto"/>
        <RowDefinition Height ="auto"/>
        <RowDefinition Height ="30"/>
        <RowDefinition Height ="*"/>
        <RowDefinition Height ="20"/>
    </Grid.RowDefinitions>

    <TextBlock Grid.Column="1" Grid.Row="1" FontSize="25" Grid.ColumnSpan="3" Text="{Binding CurrentQuestion.Question}"/>

    <StackPanel Orientation="Horizontal" Grid.Column="2" Grid.Row="3" Grid.ColumnSpan="5">
        <RadioButton FontWeight="Bold" Content="{Binding CurrentAnswer.FirstAnswer}"/>
        <RadioButton FontWeight="Bold" Margin="10 0 0 0" Content="{Binding CurrentAnswer.SecondAnswer}"/>
        <RadioButton FontWeight="Bold" Margin="10 0 0 0" Content="{Binding CurrentAnswer.ThirdAnswer}"/>
    </StackPanel>


    <Button FontWeight="Bold" x:Name="nextButton" Content="Next Question" Grid.Column="2" Grid.Row="5"/>

2 个答案:

答案 0 :(得分:0)

有一种方法是在ViewModel中公开名为MoveNext

的ICommand

ICommand界面在https://msdn.microsoft.com/en-us/library/system.windows.input.icommand(v=vs.110).aspx

class MoveNextCommand : ICommand 
{
    ...... <Your implementation>
}

public class TestViewModel 
{
    ...
    private ICommand _moveNextCmd;
    public ICommand MoveNextCmd 
    {
        get { return _moveNextCmd ?? (_moveNextCmd = new MoveNextCommand()); }
    }
    ...
}

在XAML中

<Button FontWeight="Bold" x:Name="nextButton" Content="Next Question" Grid.Column="2" Grid.Row="5" Command={Binding MoveNextCmd} />

命令的逻辑只是改变ViewModel的CurrentQuestion。

重要的是,您的ViewModel必须实现INotifyPropertyChanged接口,并且属性的setter必须调用OnPropertyChanged,否则在更改属性值时不会看到任何更新。

答案 1 :(得分:0)

如果你想避免使用后面的代码并为此实现MVVM,你需要实现ICommand。

将其放入 ViewModel

public ICommand ExecuteCommand
    {
        get
        {
            if (_command == null)
            {
                _command = new RelayCommand(param => this.NextQuestion());
            }
            return _command;
        }
    }

    public void NextQuestion()
    {
        //Do Stuff Here

    }

将此按钮添加到 XAML

,将其绑定到该按钮
Command="{Binding Path=ExecuteCommand}"

最后,在项目中添加 RelayCommand 类:

public class RelayCommand : ICommand
{

    readonly Action<object> _ActionToExecute;
    readonly Predicate<object> _ActionCanExecute;

    public RelayCommand(Action<object> inActionToExecute): this(inActionToExecute, null)
    {

    }

    public RelayCommand(Action<object> inActionToExecute, Predicate<object> inActionCanExecute)
    {
        if (inActionToExecute == null)
            throw new ArgumentNullException("execute");

        _ActionToExecute = inActionToExecute;
        _ActionCanExecute = inActionCanExecute;
    }

    public bool CanExecute(object parameter)
    {
        return _ActionCanExecute == null ? true : _ActionCanExecute(parameter);
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public void Execute(object parameter)
    {
        _ActionToExecute(parameter);
    }
}