解决 使用MVVM清除文本框

madaxe2020

会员
已加入
2020年9月7日
留言内容
17
编程经验
5-10
我不会在选择按钮并将记录添加到组合框和datagridview后清除文本框的行为

我使用MVVM作为我的模式,并将文本框绑定到我要设置为string.Empty的属性上,在创建新记录后,该文本框不会更新。

谢谢

马达克斯

XAML:
<Window x:Class="WPFBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPFBinding"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="530">
    <Grid>
        <StackPanel Width="500">
            <TextBox x:Name="TextInput" Text="{Binding  myContinentName,
                                                        Mode=TwoWay,
                                                        NotifyOnSourceUpdated=True,
                                                        UpdateSourceTrigger=PropertyChanged}"/>
            <Button Command="{Binding ButtonCommand}"
                    CommandParameter="{Binding  ElementName=TextInput,
                                                Path=Text}"
                    Content="Add to ComboBox"/>
            <ComboBox ItemsSource="{Binding myMessages}"/>
            <DataGrid x:Name="DGD_UserList"
                        AutoGenerateColumns="False" 
                        ItemsSource="{Binding   myContinents,
                                                Mode=TwoWay,
                                                NotifyOnSourceUpdated=True,
                                                UpdateSourceTrigger=PropertyChanged}"                 
                        Margin="0,5,5,5"
                        ColumnWidth="*"
                        Background="#FF9F9E9E" HorizontalAlignment="Right" Width="481">
                <DataGrid.Columns>
                    <DataGridTextColumn Binding="{Binding continent_name}" Header="Continent Name" IsReadOnly="True"/>
                    <DataGridTextColumn Binding="{Binding modifying_user_id}" Header="Modifying User" IsReadOnly="True"/>
                    <DataGridTextColumn Binding="{Binding modifying_date}" Header="Modification Date" IsReadOnly="True"/>
                </DataGrid.Columns>
            </DataGrid>
        </StackPanel>
    </Grid>
</Window>

Relay:
using System;
using System.Windows.Input;

namespace WPFBinding
{
    public class RelayCommand : ICommand
    {
        readonly Action<object> _execute;
        readonly Predicate<object> _canExecute;

        public RelayCommand(Action<object> execute, Predicate<object> canExecute)
        {
            if (execute == null)
            {
                throw new NullReferenceException("execute");
            }
            else
            {
                this._execute = execute;
                this._canExecute = canExecute;
            }
        }
        public RelayCommand(Action<object> execute) : this(execute, null)
        {

        }
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
        public bool CanExecute(object parameter)
        {
            return this._canExecute == null ? true : this._canExecute(parameter);
        }
        public void Execute(object parameter)
        {
            this._execute.Invoke(parameter);
        }
    }
}


View Model Base:
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace WPFBinding.Models.Base
{
    public class ViewModelBase : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged 会员 
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion
    }
}

View 模型:
using System;
using System.Collections.ObjectModel;
using WPFBinding.Models;
using WPFBinding.Models.Base;

namespace WPFBinding.ViewModels
{
    public class DataViewModel : ViewModelBase
    {
        public string myContinentName { get; set; }

        public ObservableCollection<Continent> myContinents { get; set; }
        public ObservableCollection<string> myMessages { get; private set; }
        public RelayCommand ButtonCommand { get; private set; }

        public DataViewModel()
        {
            this.myMessages = new ObservableCollection<string>() { };
            this.myContinents = new ObservableCollection<Continent>() { };

            this.ButtonCommand = new RelayCommand(AddtoComboBox, ComboboxCanAdd);
        }

        public void AddtoComboBox(object message)
        {
            if (this.myMessages.Contains((string)message) == false)
            {
                Continent continent = new Continent((string)message, 1, DateTime.Now);
                this.myContinents.Add(continent);
                this.myMessages.Add((string)message);

                this.myContinentName = string.Empty;
            }
        }

        public bool ComboboxCanAdd(object message)
        {
            if (string.IsNullOrWhiteSpace((string)message) == true || this.myMessages.Contains((string)message) == true)
            {
                return false;
            }
            else
            {
                return true;
            }
        }   
    }
}

Model:
using System;

namespace WPFBinding.Models
{
    public class Continent
    {
        public string continent_name { get; set; }
        public int modifying_user_id { get; set; }
        public DateTime modifying_date { get; set; }

        public Continent(string ContinentName, int ModifyingUserId, DateTime ModifyingDate)
        {
            this.continent_name = ContinentName;
            this.modifying_user_id = ModifyingUserId;
            this.modifying_date = ModifyingDate;
        }
    }
}
 

madaxe2020

会员
已加入
2020年9月7日
留言内容
17
编程经验
5-10
我不得不将ViewModelbase更改为抽象类,并将NotifyPropertyChanged更改为受保护的虚拟void

然后在视图模型中

私有字符串_myContinentName;
公共字符串myContinentName {get {返回this._myContinentName; }设置{this._myContinentName = value; base.NotifyPropertyChanged(); }}

改变我的财产

我可以用Linq或其他方法简化它吗

谢谢

马达克斯


ViewModelBase:
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace WPFBinding.Models.Base
{
    public abstract class ViewModelBase : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged 会员 
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion
    }
}
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,497
地点
弗吉尼亚州切萨皮克
编程经验
10+
如果您希望使用的是最新的C#,那么您可以尝试以下操作:
C#:
string _myContinentName;
public string MyContinentName
{
    get => _myContinentName;
    set
    {
        _myContinentName = value;
        NotifyPropertyChanged();
    }
}

Ignore ReSharper and StyleCop when it suggests using the this. and base.. The compiler will tell you when there is any ambiguity. You are already using the Hungarian naming convention of using the underscore to denote that the variable is a class field, so there should not be any confusion or ambiguity in the eyes of people reading your code.

您唯一需要使用这两个关键字的时间是:
如果您想对要访问的成员非常明确。一些团队将此作为命名约定,和/或强制使用StyleCop或ReSharper规则;
If you need to be that explicit is when you have a deep hierarchy and you have overridden some of the members using the new.

除非与您一起工作的团队的编码约定始终写为私有,否则您无需显式声明为私有。

探索使用表情浓郁的getter / setter方法。上面,我试图做吸气剂。
 
Last edited:
最佳 底部