C# WPF 绑定无法与 int 类型的属性正常工作

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1199149/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 10:42:18  来源:igfitidea点击:

WPF binding not working properly with properties of int type

c#wpfsilverlightxamldata-binding

提问by akjoshi

I am having a property of inttype in my view model which is bound to a TextBox. Everything works properly, TwoWaybinding works fine except in one case -

我的int视图模型中有一个type属性,它绑定到TextBox. 一切正常,TwoWay绑定工作正常,除非在一种情况下 -

If I clear the value of TextBox, property setter doesn't gets called and although value is cleared in TextBox, property still holds the previous value.

如果我清除 的值TextBox,则不会调用属性设置器,尽管在 中清除了值TextBox,但属性仍保留先前的值。

has anyone faced similar issue? is there any workaround for this?

有没有人遇到过类似的问题?有什么解决方法吗?

Here is the property -

这是房产——

public int MaxOccurrences
{
    get
    {
        return this.maxOccurrences;
    }
    set
    {
        if (this.maxOccurrences != value)
        {
            this.maxOccurrences = value;
            base.RaisePropertyChanged("MaxOccurrences");
        }
    }
}

Here is how I am binding the property in xaml -

这是我如何在 xaml 中绑定属性 -

<TextBox Text="{Binding Path=MaxOccurrences, Mode=TwoWay, 
    NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}" 
    HorizontalAlignment="Center" Width="30" Margin="0,0,5,0"/>

采纳答案by WPF User

I had the similar problem.

我有类似的问题。

You just need to update the code as:

您只需要将代码更新为:

<TextBox Text="{Binding Path=MaxOccurrences, Mode=TwoWay, TargetNullValue={x:Static sys:String.Empty},
NotifyOnSourceUpdated=True,  UpdateSourceTrigger=PropertyChanged}"  
HorizontalAlignment="Center" Width="30" Margin="0,0,5,0"/> 

回答by Simon P Stevens

This is partially a guess (I haven't got VS handy right now to try it out), but I think it's because a cleared text box is an empty string(""), which can't be implicitly converted to an int. You should probably implemented a type converter to provide the conversion for you. (you probably want to do something like convert "" to 0)

这部分是猜测(我现在还没有用 VS 来试用它),但我认为这是因为清除的文本框是空的string( ""),不能隐式转换为int. 您可能应该实现一个类型转换器来为您提供转换。(你可能想做一些像将 "" 转换为 0 的事情)

回答by ChrisBD

It's because an intvalue can't be null. It's best to use a stringproperty that converts the value for you within your code to the required int property field.

这是因为一个int值不能是null. 最好使用string将代码中的值转换为所需的 int 属性字段的属性。

That way you can perform a

这样你就可以执行一个

if(string.IsNullOrEmpty(text))
{
  this.intValue = 0;
}

回答by Mohammed A. Fadil

Akjoshi, I have a working solution!

Akjoshi,我有一个可行的解决方案!

You need to change your integer property to Naullable<int>(i.e. int?), see the following snippet:

您需要将整数属性更改为Naullable<int>(ie int?),请参阅以下代码段:

private int? _maxOccurrences;
public int? MaxOccurrences
{
    get { return _maxOccurrences; }
    set { _maxOccurrences = value; }
}

You also need to add a value converter to convert the empty string to null value, see the following code snippet:

您还需要添加一个值转换器来将空字符串转换为空值,请参阅以下代码片段:

public class EmptyStringToNullConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value == null || string.IsNullOrEmpty(value.ToString())
            ? null
            : value;
    }

    #endregion
}

The XAML code:

XAML 代码:

<Window x:Class="ProgGridSelection.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:System="clr-namespace:System;assembly=mscorlib" 
    xmlns:local="clr-namespace:ProgGridSelection"
    Title="MainWindow"
    Height="136" Width="525"
    Loaded="OnWindowLoaded">
<Window.Resources>
    <local:EmptyStringToNullConverter x:Key="EmptyStringToNullConverter"/>
</Window.Resources>
<StackPanel>
    <Button Content="Using Empty String to Null Converter"/>
    <TextBox Name="empNameTextBox"
             Text="{Binding Mode=TwoWay, Path=MaxOccurrences,
                RelativeSource={RelativeSource FindAncestor, AncestorType=Window},
                Converter={StaticResource EmptyStringToNullConverter}}"/>
</StackPanel>

[Note: this is just a proof of concept, and for the sake of simplicity I didn't use any patterns or best practices]

[注意:这只是一个概念证明,为了简单起见,我没有使用任何模式或最佳实践]

回答by Mohammed A. Fadil

If you don't want to use a Nullableinteger, you can use a converterthat converts the empty stringto 0, see the code below:

如果不想使用 a Nullableinteger,可以使用 aconverter将空string值转换为 0,请参阅下面的代码:

public class EmptyStringToZeroConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value == null || string.IsNullOrEmpty(value.ToString())
            ? 0
            : value;
    }

    #endregion
}

回答by R.Titov

I have the same problem, but I need to handle and not numeric value to. I use the following converter for this:

我有同样的问题,但我需要处理而不是数值。我为此使用以下转换器:

public class StringFormatToIntConverter : IValueConverter
{            
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
          return value.ToString();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
       if(value is string)
       {
           var inttext = 
            System.Text.RegularExpressions.Regex.Replace((string)value, "[^.0-9]", "");

           int number;
           return Int32.TryParse(inttext, out  number) ? number : 0;
       }
       else
       {
           return value;
       }
    }
}