首页 文章

数据绑定不在WinRT弹出窗口中更新

提问于
浏览
1

我有一个弹出窗口(下面的相关部分):

<Flyout x:Key="flyoutAverage" FlyoutPresenterStyle="{StaticResource flyoutPresenter}" Closed="Flyout_Closed">
  <Grid>
    <TextBox Grid.Row="1" Grid.Column="0" Text="{Binding One, Mode=TwoWay}" InputScope="Number" Margin="5,0" />
    <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Two, Mode=TwoWay}" InputScope="Number" Margin="5,0"  />
    <TextBox Grid.Row="1" Grid.Column="2" Text="{Binding Three, Mode=TwoWay}" InputScope="Number" Margin="5,0"  />
    <TextBlock Grid.Row="1" Grid.Column="3" FontSize="18" VerticalAlignment="Center" Text="{Binding Average}" />
 </Grid>
</Flyout>

通过此按钮显示:

<StackPanel Orientation="Horizontal" DataContext="{Binding Neck}">
  ...
  <Button Flyout="{StaticResource flyoutAverage}">Enter</Button>
</StackPanel>

按钮(和Flyout)的数据上下文是此对象的一个实例:

public decimal One
{
  get { return m_One; }
  set { m_One = value; PropChanged("First"); PropChanged("Average"); }
}
public decimal Two
{
  get { return m_Two; }
  set { m_Two = value; PropChanged("Second"); PropChanged("Average"); }
}
public decimal Three
{
  get { return m_Three; }
  set { m_Three = value; PropChanged("Third"); PropChanged("Average"); }
}
public decimal Average
{
  get
  {
    return (One + Two + Three) / 3;
  }
}

预期的行为是,当用户点击按钮时,会显示以下信息:
Screenshot

用户在每个文本框中输入值,“平均”文本块将自动更新为平均值 .

文本框中填充了正确的值,但永远不会被推回到对象 . 当我关闭Flyout并将其打开时,值将保留 . 就好像绑定模式是OneWay,当它明确设置为TwoWay时 .

有任何想法吗?或者我只是做错了?

3 回答

  • 2

    在进行 TwoWay 绑定时,如果不处理数据转换,则无法直接从 TextBox 绑定到 decimal . TextBox Text 属性的类型为字符串 . 像这样的简单转换器是必要的(使用 IValueConverterreference)):

    public class DecimalConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, 
                              object parameter, string language)
        {
            return value.ToString();
        }
    
        public object ConvertBack(object value, Type targetType, 
                                  object parameter, string language)
        {
            decimal d;
            if (value is string)
            {
                if (decimal.TryParse((string)value, out d))
                {
                    return d;
                }
            }
            return 0.0;
        }
    }
    

    并作为 Resource

    <local:DecimalConverter x:Key="decimalConverter" />
    

    然后,在使用中:

    <TextBox Grid.Row="1" Grid.Column="0" 
            Text="{Binding One, Mode=TwoWay, 
                     Converter={StaticResource decimalConverter}}" 
            InputScope="Number" Margin="5,0" />
    

    InputScope 只是建议Windows,当字段获得焦点时,默认情况下应该显示什么键盘 . 它不会阻止不需要的键(或字母字符) .

    此外,请务必使用要更改的属性的名称调用 PropChanged . 他们的代码错了 .

    当绑定在XAML / WPF应用程序中无法正常工作时,您应始终使用的一件事是检查Visual Studio Output 窗口是否有错误 . 你会看到类似这样的东西:

    错误:无法将目标值保存到源 . BindingExpression:Path ='Two'DataItem ='Win8CSharpTest.NeckData,Win8CSharpTest,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'; target元素是'Windows.UI.Xaml.Controls.TextBox'(Name ='null'); target属性是'Text'(类型'String') .

  • 0

    只是为了分享如果有人在将来遇到这个问题,我使用了上面的转换器,但是我的大脑仍在讨论为什么转换不起作用 . 实际上,我的语言环境的Decimal分隔符是“,”而不是“ . ” . 所以,为了解决这个问题,我修改了转换器如下:

    public class DecimalConverter : IValueConverter
        {
            public object Convert(object value, Type targetType,
                                  object parameter, string language)
            {
                return value.ToString();
            }
    
            public object ConvertBack(object value, Type targetType,
                                      object parameter, string language)
            {
                if (value is string)
                {
                    decimal d;
                    var formatinfo = new NumberFormatInfo();
    
                    formatinfo.NumberDecimalSeparator = ".";
    
                    if (decimal.TryParse((string)value, NumberStyles.Float, formatinfo, out d))
                    {
                        return d;
                    }
    
                    formatinfo.NumberDecimalSeparator = ",";
    
                    if (decimal.TryParse((string)value, NumberStyles.Float, formatinfo, out d))
                    {
                        return d;
                    }
                }
                return 0.0;
            }
        }
    
  • 3

    我更喜欢处理字符串格式化和绑定的更通用的解决方案:

    public class StringFormatConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            if (value == null)
            {
                return string.Empty;
            }
            return string.Format((parameter as string) ?? "{0}", value);
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            if (string.IsNullOrEmpty(System.Convert.ToString(value)))
            {
                if (targetType.IsNullable())
                {
                    return null;
                }
                return 0;
            }
    
            if (targetType == typeof (double))
            {
                return System.Convert.ToDouble(value);
            }
            if (targetType == typeof(decimal))
            {
                return System.Convert.ToDecimal(value);
            }
            if (targetType == typeof(int))
            {
                return System.Convert.ToInt16(value);
            }
            if (targetType == typeof(Int32))
            {
                return System.Convert.ToInt32(value);
            }
            return value;
        }
    }
    

    用法:

    <TextBox InputScope="Number" Text="{Binding Path=Model.SalesPrice, Mode=TwoWay, Converter={StaticResource StringFormatConverter}, ConverterParameter='{}{0:N2}'}">
    

    这会将显示值和输入的值都转换回源 .

相关问题