【问题标题】:textbox automatically assigning default value wpf文本框自动分配默认值 wpf
【发布时间】:2019-05-20 14:31:49
【问题描述】:

我开始通过练习一个简单的加法程序来学习使用 mvvm 的 wpf。我的应用程序运行良好。

但在运行应用程序时,文本框会自动分配默认值 0。

在用户提供任何输入之前我不希望 0。

view.xaml:

 <TextBox Height="28" Margin="112,56,46,0"  Text ="{Binding firstargument}"   Name="textBox1" VerticalAlignment="Top" />

ViewModel.cs

  private string _number1;
        public string firstargument
        {
            get { return _number1; }
            set
            {
                this._number1 = value;
                this.OnPropertyChanged("firstargument");

            }
        }

我的问题是执行后删除文本框中的值 0?

已编辑

ModelView.cs

 class ViewModel : INotifyPropertyChanged
    {


        public RelayCommand AddNew { get; set; }

        private int _number1;
        public int firstargument
        {
            get { return _number1; }
            set
            {


                this._number1 = value;
                this.OnPropertyChanged("firstargument");

            }
        }

        private int _number2;

        public int secondargument
        {
            get { return _number2; }
            set
            {
                this._number2 = value;

                this.OnPropertyChanged("secondargument");
            }
        }

        private int _number3;

        public int _addedargument
        {
            get { return _number3; }
            set
            {
                _number3 = value;
                this.OnPropertyChanged("_addedargument");
            }
        }
    public  ViewModel()
    {

        AddNew = new RelayCommand(o => AddNumbers());
    }


    private void AddNumbers()
    {
//Model instance is created here.
        Number p = new Number() { number1 = this._number1, number2 = this._number2 };

        var c = p.number1 + p.number2;
        _addedargument = c;

    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion

    }

view.Xaml

<Window x:Class="addition.Window1"
         xmlns:vm="clr-namespace:addition.ViewModel" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Window.DataContext>
        <vm:ViewModel />
    </Window.DataContext>
    <Grid>

        <Label Height="28" Margin="28,54,0,0" Name="Number1" VerticalAlignment="Top" HorizontalAlignment="Left" Width="48">Number</Label>
        <TextBox Height="28" Margin="112,56,46,0"  Text ="{Binding Path = firstargument}"   Name="textBox1" VerticalAlignment="Top" />
        <Label Margin="28,106,0,128" Name="Number2" Width="58" HorizontalAlignment="Left">Number1</Label>
        <TextBox Height="28" Margin="112,120,46,120" Text ="{Binding  Path = secondargument }" Name="textBox2" />
        <Label Height="28" Margin="28,0,0,75" Name="label1" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="58">Number2</Label>
        <TextBox Height="23" Margin="112,0,46,68" Name="textBox3" Text="{Binding _addedargument}" VerticalAlignment="Bottom" />
        <Button Height="23"  HorizontalAlignment="Left" Margin="39,0,0,16" Name="button1" VerticalAlignment="Bottom" Width="75" Command="{Binding AddNew}">Button</Button>
    </Grid>
</Window>

编辑:实施 walteerlv 解决方案后,以下添加逻辑不起作用:

class ViewModel : INotifyPropertyChanged
    {
        int num;


        public RelayCommand AddNew { get; set; }

       private int? _number1;

public string FirstArgument
{

    get { return  _number1.ToString();}
    set
    {
        if (int.TryParse(_number1.ToString(), out num ))
        {
            this._number1 = num;
            OnPropertyChanged("FirstArgument");
        }
        else
        {
            _number1 = null;
        }
    }
}
        private int? _number2;

        public string secondargument
        {
            get { return _number2.ToString(); }

            set
            {
                if (int.TryParse(_number1.ToString(), out num))
                {
                    this._number2 = num;

                    this.OnPropertyChanged("secondargument");
                }
                else
                {
                    _number2 = null;
                }
            }
        }

        private int? _number3;

        public string _addedargument
        {
            get { return _number3.ToString(); }
            set
            {
                if (int.TryParse(_number1.ToString(), out num))
                {
                    this._number3 = num;

                    this.OnPropertyChanged("secondargument");
                }
                else
                {
                    _number3 = null;
                }
            }
        }



        public  ViewModel()
    {
        // The command receives an action on the constructor,
        // which is the action to execute when the command is invoked.


        AddNew = new RelayCommand(o => AddNumbers());



    }


    private void AddNumbers()
    {

        Number p = new Number() { number1 =this._number1.ToString(), number2 = this._number2.ToString() };

        MessageBox.Show(this._number1.ToString());
        int? c = Int32.Parse(p.number1) + Int32.Parse(p.number2);
        _addedargument = c.ToString();


    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion

    }

如果您需要更多信息,请告诉我。

【问题讨论】:

  • 我已经尝试了您提供的所有代码,但我得到了一个没有任何意外字符串的空 TextBlock,例如 0。因此,您可能丢失了其他影响此行为的重要代码。
  • @walterlv 我已经提供了视图模型和视图的完整代码。让我知道您是否可以复制该行为。
  • 这个问题有很多编辑,很难理解。该问题需要提供单个minimal reproducible example。我怀疑您只需要在绑定上使用 Converter,并将该属性设置为可为空的 int。其他提示:与其使用字符串来包含属性名称,不如使用nameof(YourProperty)。您可以使用CallerMemberName 更进一步,这样大多数时候您甚至不需要这样做。

标签: c# wpf


【解决方案1】:

我将模型的 int 属性包装在一个字符串属性中,因为 TextBox.Text 是一个字符串,其他任何内容都会产生转换错误。

ViewModel 需要自己的字符串,而不是总是将用户的输入转换为 int,因为用户可能会清除该框,或者在输入“-1”的过程中部分输入了一个不是有效数字的值。当你收到转换错误时,WPF 绑定无法更新视图模型,所以你不知道有问题。

    private string firstArgument;

    public string FirstArgument
    {
        get
        {
            return this.firstArgument;
        }

        set
        {
            this.firstArgument= value;

            int tempInt;
            if (int.TryParse(value, out tempInt))
            {
                this.Model.FirstArgument = tempInt;
            }

            this.NotifyPropertyChanged();
        }
    }

以下是我用来验证字符串是否为有效 int 的大部分代码。

    protected void NotifyPropertyChanged([CallerMemberName]string propertyName = null)
    {
        this.CheckForPropertyErrors();

        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }


    public override void CheckForPropertyErrors()
    {
        this.ValidateInt(this.FirstArgument , nameof(this.FirstArgument ));
    }


    protected void ValidateInt32(string value, string fieldName, string displayName = null)
    {
        int temp;
        if (!int.TryParse(value, out temp))
        {
            this.AddError(new ValidationError(fieldName, Constraints.NotInt32, $"{displayName ?? fieldName} must be an integer"));
        }
        else
        {
            this.RemoveError(fieldName, Constraints.NotInt32);
        }
    }

【讨论】:

    【解决方案2】:

    int 变量的默认值为0。我想,这会对你有所帮助

     private int? _number1;
        public int? firstargument
        {
            get { return _number1; }
            set
            {
                this._number1 = value;
                this.OnPropertyChanged("firstargument");
            }
        }
    

    【讨论】:

      【解决方案3】:

      原因

      你在运行窗口中得到0的原因是你的绑定属性都是int,而0int的默认值。

      int 中的0 是 XAML 绑定系统的有效值,因此在您键入任何内容之前,您会看到所有 TextBoxes 都包含一个 0


      解决方案

      您的所有属性都应该是 string 并转换您的实际数字:

      private int? _number1;
      
      public string FirstArgument
      {
          get => _number1?.ToString();
          set
          {
              if (int.TryParse(value, out var number))
              {
                  _number1 = number;
                  OnPropertyChanged("FirstArgument");
              }
              else
              {
                  _number1 = null;
              }
          }
      }
      

      注意:

      1. 由于您可能会得到无法转换为int 的文本,因此您可以在输入错误号时使用int? 存储空值。
      2. 将您的号码转换为字符串或从字符串转换,以便它可以正确显示到您的 XAML 绑定系统中。
      3. 属性应该是字符串,不能是int?,因为XAML绑定系统不会自动将string转换成int,除非你自己转换或者写一个新的IValueConverter

      更新

      要实现Add 命令,只需使用字段而不是属性。

      private void AddNumbers()
      {
          var a = _number1?.Value ?? 0;
          var b = _number2?.Value ?? 0;
          var c = a + b;
          _addedargument = c;
      }
      

      如果要将结果存储到模型中,则存储 abc 值。

      【讨论】:

      • @walteerlv 感谢您的评论,我已更改代码,问题已解决。但是现在我的添加逻辑在更改代码后不起作用。我在更改后更新了有问题的新代码。
      • 您的添加命令需要更改为使用int? 而不是字符串。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-08
      • 1970-01-01
      • 2015-03-05
      • 2011-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多