WPF MVVM模型中的按钮命令 [英] Button Command in WPF MVVM Model

查看:72
本文介绍了WPF MVVM模型中的按钮命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在MainWindow中有两个UserControl,UserControl2有两个Listbox,Texbox和Buttons。当我在TextBox中写一些文本并按下Button时,它应该添加到ListBox中。有人帮我代码,我是新手WPF和MVVM



这是我的XAML代码

I have two UserControls in my MainWindow and UserControl2 has 2 Listboxes,Texboxes and Buttons.When i write some text in TextBox and press Button it should add into the ListBox.Can somebody help me with the code,i'm new to WPF and MVVM

This is my XAML code

<Window x:Class="Wpf_MVVM.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Wpf_MVVM" 
    Title="title" removed="SlateGray" Height="420" Width="550">


<Grid>
    <local:UserControl1 HorizontalAlignment="Left" VerticalAlignment="Top"/>
    <local:UserControl2 HorizontalAlignment="Left" VerticalAlignment="Top" Margin="150,29,0,0"/>




</Grid>





这是我的UserControl1.Xaml代码



This is my UserControl1.Xaml code

<UserControl x:Class="Wpf_MVVM.UserControl1"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         Height="Auto" Width="Auto">
<Grid>
    <ListBox HorizontalAlignment="Left" Height="310" VerticalAlignment="Top" Width="150" Margin="0,40,0,0">
        <ListBoxItem>Name 1</ListBoxItem>
        <ListBoxItem>Name 2</ListBoxItem>
        <ListBoxItem>Name 3</ListBoxItem>
        <ListBoxItem>Name 4</ListBoxItem>
        <ListBoxItem>Name 5</ListBoxItem>
        <ListBoxItem>Name 6</ListBoxItem>
    </ListBox>
    <Label Content="Conversations" HorizontalAlignment="Left" VerticalAlignment="Top"  Height="40" Width="150" FontSize="20" Background="SkyBlue"/>
    <Button Content="Create New Chat" Height="30" HorizontalAlignment="Left" Margin="0,350,0,0" VerticalAlignment="Top" Width="150"/>

</Grid>



这是我的UserControl2.Xaml代码


This is my UserControl2.Xaml code

<UserControl x:Class="Wpf_MVVM.UserControl2"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         Height="Auto" Width="390">
<Grid>
    <ListBox Name="listbox1" HorizontalAlignment="Left" Height="310" VerticalAlignment="Top" Width="180" Margin="10,0,0,0"/>
    <ListBox Name="listbox2"  HorizontalAlignment="Left" Height="310" Margin="200,0,0,0" VerticalAlignment="Top" Width="180"/>
    <TextBox Name="tb1" HorizontalAlignment="Left" Height="40" Margin="200,310,0,0" TextWrapping="NoWrap" Text="" VerticalAlignment="Top" Width="130"/>
    <TextBox Name="tb2" Height="40" TextWrapping="NoWrap" Text="" Margin="10,310,245,0"/>
    <Button Command="{Binding ButtonCommand}" Name="btn1" Content="Send" Height="40" HorizontalAlignment="Left" Margin="330,310,0,0" VerticalAlignment="Top" Width="50" />
    <Button Command="{Binding SendControlCommand}" Name="btn2" Content="Send" Height="40" Margin="145,310,200,0"/>

</Grid>

推荐答案

如果你想使用相同的 ViewModel 两个控件或者如果你希望 UserControl1 ViewModel UserControl2 <不同/ code>; s ViewModel ,因为这需要你让 ViewModel 相互沟通。



如果我们假设更简单的情况(两个控件共享一个 ViewModel ),那么你的实现是在正确的轨道上。



只需将 ListBox es绑定到 ViewModel 上的项目源,并在 Button 单击code>。您可以方便地使用 ObservableCollection 作为物品来源的容器。



切割 - 示例可能看起来像这样;



UserControl1.xaml

There is a big difference if you want to use the same ViewModel for both controls or if you want the ViewModel of UserControl1 to be different from UserControl2;s ViewModel, as that would require you have your ViewModels communicate with each other.

If we assume the simpler case (both controls share a single ViewModel) then your implementation is on the right track.

Just make your ListBoxes bind to an item source on the ViewModel, and add to that source when the Button is clicked. It might be convenient for you to use an ObservableCollection as the container for the item source.

A cut-down example might look something like this;

UserControl1.xaml
<usercontrol x:class="WpfMvvm.UserControl1" xmlns:x="#unknown">
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             Background="CornflowerBlue" Padding="10">
    <grid>
        <grid.rowdefinitions>
            <rowdefinition height="Auto" />
            <rowdefinition height="*" />
            <rowdefinition height="Auto" />
        </grid.rowdefinitions>
        <label grid.row="0" content="This list is based on items from UserControl2" />
        <listbox grid.row="1" itemssource="{Binding Path=Items, Mode=OneWay}" />
        <button grid.row="2" content="Clear" command="{Binding Path=ClearCommand, Mode=OneWay}" />
    </grid>
</usercontrol>





UserControl2.xaml



UserControl2.xaml

<usercontrol x:class="WpfMvvm.UserControl2" xmlns:x="#unknown">
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             Background="DarkSalmon" Padding="10">
    <stackpanel>
        <label content="Enter string:" />
        <textbox text="{Binding Path=Text, Mode=TwoWay}" />
        <button content="Add" command="{Binding Path=AddCommand, Mode=OneWay}" />
    </stackpanel>
</usercontrol>





ViewModel.cs



ViewModel.cs

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;

namespace WpfMvvm {
    public class ViewModel : INotifyPropertyChanged {

        public event PropertyChangedEventHandler PropertyChanged;

        private readonly ObservableCollection<string> items = new ObservableCollection<string>();
        private string text;

        private readonly ICommand clearCommand;
        private readonly ICommand addCommand;

        public ViewModel() {
            clearCommand = new Command(items.Clear);
            addCommand = new Command(() => items.Add(Text));
        }

        private void Notify(string propertyName) {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }

        public IEnumerable<string> Items {
            get { return items; }
        }

        public ICommand ClearCommand {
            get { return clearCommand; }
        }

        public ICommand AddCommand {
            get { return addCommand; }
        }

        public string Text {
            get { return text; }
            set {
                if (text == value)
                    return;

                text = value;
                Notify("Text");
            }
        }
    }
}
</string></string></string>





MainWindow.xaml



MainWindow.xaml

<window x:class="WpfMvvm.MainWindow" xmlns:x="#unknown">
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:l="clr-namespace:WpfMvvm"
        Title="MainWindow" Height="350" Width="525">
    <grid>
        <grid.rowdefinitions>
            <rowdefinition height="*" />
            <rowdefinition height="Auto" />
        </grid.rowdefinitions>
        <l:usercontrol1 grid.row="0" xmlns:l="#unknown" />
        <l:usercontrol2 grid.row="1" xmlns:l="#unknown" />
    </grid>
</window>





MainWindow.xaml.cs



MainWindow.xaml.cs

namespace WpfMvvm {
    public partial class MainWindow {
        public MainWindow() {
            InitializeComponent();
            DataContext = new ViewModel();
        }
    }
}





希望这有帮助,

Fredrik



Hope this helps,
Fredrik


你应该首先按如下方式实现INotifyPropertyChanged:



You should first implement the INotifyPropertyChanged as follows:

public event PropertyChangedEventHandler PropertyChanged;
        public void NotifyPropertyChanged(string propertyname)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
            }
        }







定义如下属性:






Define a property like this:

private string _contentToAdd;




public string ContentToAdd
{
   get { return this._contentToAdd; }
   set { this._contentToAdd = value; NotifyPropertyChanged("ContentToAdd"); }
}





在XAML中,您可以将文本框输入绑定到此属性:





In XAML, you can bind the textbox input to this property:

<textbox name="tb1" text="{Binding ContentToAdd}" />





不要忘记设置数据上下文视图,否则,绑定将不起作用。



最后要做的是创建一个集合,您可以在其中添加您在文本框中创建的每个条目并将列表框的项目来源设置为集合。



这应该有效......我如果您有任何其他问题,请询问。



编辑:



当然:

首先,使用此命名空间:



And don't forget to set the data context of the view, otherwise, the binding won't work.

Last thing to do is to create a collection where you can add each entry you made in your text box and set the item source of your list box to the collection.

This should work...if you have any further questions, just ask.



Sure:
First, use this namespace:

using System.Collections.ObjectModel;





然后,定义集合的属性:





Then, define property for the collection:

private ObservableCollection<string> _yourList;
public ObservableCollection<string> YourList
{
   get{return this._yourList;}
   set{this._yourList = value; NotifyPropertyChanged;}
}





不要忘记在构造函数中实例化集合:





Don't forget to instantiate the collection in your constructor:

_yourList = new ObservableCollection<string>();







在添加命令中,将字符串添加到此集合中:






In your add command, add the string to this collection:

yourList.Add(ContentToAdd);





在XAML中:





In XAML:

<ListBox ItemsSource ="{Binding YourList}"/>





编辑v2:





创建新课程:





EDIT v2:


Create new class:

class DelegateCommand : ICommand
    {
        private readonly Predicate<object> _canExecute;
        private readonly Action<object> _execute;

        public event EventHandler CanExecuteChanged;

        public DelegateCommand(Action<object> execute)
        {
            _execute = execute;
        }

        public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
        {
            _execute = execute;
            _canExecute = canExecute;
        }



        public bool CanExecute(object parameter)
        {
            if (_canExecute == null)
            {
                return true;
            }

            return _canExecute(parameter);
        }

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

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







在ViewModel中:






In your ViewModel:

public ICommand AddCommand{get;set;}
public void Add(object parameter)
{
   YourList.Add(ContentToAdd);
}





在构造函数中实例化你的命令:





Instantiate your command in your constructor:

AddCommand = new DelegateCommand(Add);





最后在你的XAML中:





And finally in your XAML:

<Button Command="{Binding AddCommand}"/>





请试一试。



Try this please.


这篇关于WPF MVVM模型中的按钮命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆