1

我有一个 Flyout(下面的相关部分):

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

预期的行为是,当用户单击按钮时,他们会看到以下内容: 截屏

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

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

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

4

3 回答 3

3

在进行绑定时,如果不处理数据转换,则不能直接绑定到decimala 。该属性是字符串类型。像这样的简单转换器是必要的(使用(参考)):TextBoxTwoWayTextBox TextIValueConverter

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 StudioOutput窗口中的错误。例如,您会看到如下内容:

错误:无法将值从目标保存回源。BindingExpression: Path='Two' DataItem='Win8CSharpTest.NeckData, Win8CSharpTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'; 目标元素是'Windows.UI.Xaml.Controls.TextBox'(名称='null');目标属性是“文本”(类型“字符串”)。

于 2014-02-08T16:31:35.387 回答
2

只是为了分享将来是否有人遇到这个问题,我使用了上面的转换器,但我绞尽脑汁想为什么转换不起作用。碰巧的是,我的语言环境的小数分隔符是“,”而不是“。”。因此,为了解决这个问题,我对转换器进行了如下修改:


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

于 2014-05-30T08:26:48.337 回答
0

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

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

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

于 2015-05-22T13:34:39.130 回答