C# WPF MVVM:需要格式的文本框和IsDefault设置为True的按钮

C# WPF MVVM:需要格式的文本框和IsDefault设置为True的按钮,c#,wpf,mvvm,binding,.net-4.0,C#,Wpf,Mvvm,Binding,.net 4.0,我也发现了类似的问题,除了我的文本框需要在焦点丢失后有一个格式化的值 <TextBox Text="{Binding Value}" MaxLength="{Binding MaskLength}"/> <Button Command="{Binding ExecuteCommand}" IsDefault="True"/> 这是我发现的黑客背后最干净的代码。我把它变成了一个附属的财产,但闻起来还是不太对劲 private void _HandleTxtKeyDown(

我也发现了类似的问题,除了我的文本框需要在焦点丢失后有一个格式化的值

<TextBox Text="{Binding Value}" MaxLength="{Binding MaskLength}"/>
<Button Command="{Binding ExecuteCommand}" IsDefault="True"/>
这是我发现的黑客背后最干净的代码。我把它变成了一个附属的财产,但闻起来还是不太对劲

private void _HandleTxtKeyDown( object sender, KeyEventArgs e )
{
    if( e.Key == Key.Enter )
    {
        TextBox textBox = (TextBox)sender;
        BindingExpression binding = textBox.GetBindingExpression( TextBox.TextProperty );
        if( binding != null )
        {
            binding.UpdateSource();
        }
    }
}

如果我以正确的方式理解你的意图,事实上没有问题

如果用户按enter键/单击按钮,您只想屏蔽输入,对吗?然后,您已经找到的解决方案(UpdateSourceTrigger=PropertyChanged)将完全按照您的意愿执行。键入时,VM中的属性将更新。如果使用PropertyChanged触发器,则在按enter键/单击按钮之前不会执行该命令

默认的UpdateSourceTrigger为“LostFocus”。当然,如果用鼠标单击按钮,而不是按enter键,也会发生这种情况


希望我能帮助你理解这个机制。

你说得不对。如果命令更新文本,则在键入时不会执行该命令,直到您按enter键/单击该按钮

观点:

<Window x:Class="WpfApplication9.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <StackPanel>
        <TextBox MaxLength="{Binding Path=MyLength}" 
                 Text="{Binding Path=MyText, UpdateSourceTrigger=PropertyChanged}"/>

        <Button Command="{Binding Path=MyCommand}" IsDefault="True">Enter</Button>
    </StackPanel>
 </Window>

进来
viewmodel,在构造函数中指定为窗口的DataContext:

public class MyViewModel : INotifyPropertyChanged
{
    private string _myText = string.Empty;
    private int _maxLength = 6;
    private ICommand _myCommand;

    public MyViewModel()
    {
        this._myCommand = new MySimpleCommand((obj) => { FormatMyText(); });
    }

    private void FormatMyText()
    {
        this.MyText = this.MyText.PadLeft(this.MyLength, '0');
    }

    public string MyText
    {
        get { return this._myText; }
        set
        {
            this._myText = value;
            PropertyChanged(this, new PropertyChangedEventArgs("MyText"));
        }
    }

    public int MyLength
    {
        get { return this._maxLength; }
        set { }
    }

    public ICommand MyCommand
    {
        get { return this._myCommand; }
        set { }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public class MySimpleCommand : ICommand
    {
        private Action<object> _action;

        public MySimpleCommand(Action<object> cmdAction)
        {
            this._action = cmdAction;
        }

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public event EventHandler CanExecuteChanged;

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

    }
}
公共类MyViewModel:INotifyPropertyChanged
{
私有字符串_myText=string.Empty;
私有int_maxLength=6;
私人ICommand_myCommand;
公共MyViewModel()
{
this._myCommand=newmysimpleCommand((obj)=>{FormatMyText();});
}
私有void FormatMyText()
{
this.MyText=this.MyText.PadLeft(this.MyLength,'0');
}
公共字符串MyText
{
获取{返回此。\u myText;}
设置
{
这个。_myText=值;
PropertyChanged(这是新的PropertyChangedEventArgs(“MyText”);
}
}
公共国际长度
{
获取{返回这个。_maxLength;}
集合{}
}
公共ICommand MyCommand
{
获取{返回此。_myCommand;}
集合{}
}
公共事件属性更改事件处理程序属性更改;
公共类MySimpleCommand:ICommand
{
私人行动;
public MySimpleCommand(Action cmdAction)
{
这是。_action=cmdAction;
}
公共布尔CanExecute(对象参数)
{
返回true;
}
公共事件处理程序CanExecuteChanged;
public void Execute(对象参数)
{
_作用(参数);
}
}
}

将其设置为PropertyChanged会更新源代码,但格式设置正确。假设我想将值'ab1'格式化为'00AB1'。如果在用户点击“a”时设置为PropertyChanged,则该值将变为“0000A”。现在用户点击“b”,它被忽略,因为已达到最大长度。不,不是。请参阅我的下一个答案,以查看完全工作的代码(已测试):我建议您在MyText属性的setter和FormatMyText()方法中放置断点。希望我能帮助你。是的,那很有效。但是,我的命令没有进行格式化。值属性在更新绑定时进行格式化(OnLostFocus[default]或PropertyChanged)。
public class MyViewModel : INotifyPropertyChanged
{
    private string _myText = string.Empty;
    private int _maxLength = 6;
    private ICommand _myCommand;

    public MyViewModel()
    {
        this._myCommand = new MySimpleCommand((obj) => { FormatMyText(); });
    }

    private void FormatMyText()
    {
        this.MyText = this.MyText.PadLeft(this.MyLength, '0');
    }

    public string MyText
    {
        get { return this._myText; }
        set
        {
            this._myText = value;
            PropertyChanged(this, new PropertyChangedEventArgs("MyText"));
        }
    }

    public int MyLength
    {
        get { return this._maxLength; }
        set { }
    }

    public ICommand MyCommand
    {
        get { return this._myCommand; }
        set { }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public class MySimpleCommand : ICommand
    {
        private Action<object> _action;

        public MySimpleCommand(Action<object> cmdAction)
        {
            this._action = cmdAction;
        }

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public event EventHandler CanExecuteChanged;

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

    }
}