代码之家  ›  专栏  ›  技术社区  ›  Mike Christiansen

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

  •  1
  • Mike Christiansen  · 技术社区  · 12 年前

    我有一张传单(下面的相关部分):

    <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>
    

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

    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

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

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

    有什么想法吗?还是我做错了?

    3 回复  |  直到 12 年前
        1
  •  3
  •   WiredPrairie    12 年前

    您不能直接绑定到 decimal 来自 TextBox 而不需要处理数据转换 TwoWay 结合这个 文本框 Text 属性的类型为string。需要这样一个简单的转换器(使用 IValueConverter ( reference )):

    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:路径=“两个”DataItem=“Win8CSharpTest.NeckData, Win8CSharpTest,版本=1.0.0.0,文化=中性, PublicKeyToken=null';目标元素是 'Windows.UI.Xaml.Controls.TextBox'(名称='ull');目标属性为 “文本”(类型“字符串”)。

        2
  •  2
  •   badikumar    12 年前

    为了分享如果将来有人面临这个问题,我使用了上面的转换器,但我绞尽脑汁想知道为什么转换不起作用。碰巧,我的区域设置的十进制分隔符是“,”,而不是“.”。因此,为了解决这个问题,我修改了转换器如下:

    
        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
  •  0
  •   Sven    11 年前

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

     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}'}">
    

    这将显示值和输入值转换回源。