【问题标题】:Coercion in Silverlight does not workSilverlight 中的强制功能不起作用
【发布时间】:2011-09-01 10:54:51
【问题描述】:

我有一个如下所示的自定义控件:

generic.xaml

<Style TargetType="controls:MyControl">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="controls:MyControl">
        <Grid>
          <Grid.RowDefinitions>
            <RowDefinition Height="20" />
            <RowDefinition Height="20" />
          </Grid.RowDefinitions>
          <TextBox Grid.Row="0"
                   Text="{Binding ElementName=slider, Path=Value}" />
          <Slider Grid.Row="1" Name="slider" Width="120"
                  Minimum="1" Maximum="12"
                  Value="{Binding Mode=TwoWay,
                          RelativeSource={RelativeSource TemplatedParent},
                          Path=Value}"/>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

MyControl.cs

public static readonly DependencyProperty ValueProperty =
  DependencyProperty.Register("Value",
  typeof(double),
  typeof(MyControl),
  new PropertyMetadata(0d, OnValueChanged));

  public double Value
  {
    get { return (double)base.GetValue(ValueProperty); }
    set { base.SetValue(ValueProperty, value); }
  }

  private static void OnValueChanged(DependencyObject source,
                                     DependencyPropertyChangedEventArgs e)
  {
    MyControl myControl = (MyControl)source;
    myControl.OnValueChanged((double)e.OldValue, (double)e.NewValue);
  }

  protected virtual void OnValueChanged(double oldValue, double newValue)
  {
    double coercedValue = CoerceValue(newValue);
    if (coercedValue != newValue)
    {
      this.Value = coercedValue;
    }
  }

  private double CoerceValue(double value)
  {
    double limit = 7;
    if (value > limit)
    {
      return limit;
    }
    return value;
  }

TextBox 只是一个显示值的虚拟对象。

现在,当我将此控件添加到应用程序时,我可以将 Slider 值设置为大于 7,尽管我的 DependencyProperty 的值设置为 7。

我做错了什么? TwoWayBinding 在这种情况下不起作用吗?

提前致谢

【问题讨论】:

  • “我能够将 Slider 的值设置为大于 7”您如何确切地管理它,我无法重现这一点。控件的行为完全符合我的预期。
  • 我希望,当我尝试将 Sliders 值更改为大于 7 的值时,它会卡住。当我在普通应用程序中添加滑块(周围没有自定义控件)并在 ValueChanged-Event 中实现我的强制逻辑时,就会出现这种行为。但在我的情况下,它不会停留在值 7。可以将所有值设置为 1 到 12
  • 我已将您的确切代码剪切并粘贴到模板化自定义控件中,并且 Slider 停留在 7 处,我无法超越。我似乎根本无法重现您所看到的问题。您正在使用 Silverlight 4?
  • @AnthonyWJones 你有没有拿一个新的空项目进行测试并且仍然有它?如果您的解决方案可以在我的计算机上运行,​​我很感兴趣。你能给我吗?如果它在运行,我可以做一个比较,也许我找到了魔力。
  • Repro 的完整步骤添加为答案,工作正常。

标签: c# silverlight binding coercion


【解决方案1】:

我的复制步骤:-

  • 在 VS2010 调用 SilverlightApplication1 中创建一个全新的 Silverlight 应用程序。
  • 向 silverlight 项目添加新的“Silverlight 模板化控件”,并将其命名为“MyControl”。
  • 将内部内容或您的 ControlTemplate 复制到主题/Generic.xaml 文件的 ControlTemplate 中。整个通用文件如下所示:-

    <Style TargetType="local:MyControl">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:MyControl">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="20" />
                            <RowDefinition Height="20" />
                        </Grid.RowDefinitions>
                        <TextBox Grid.Row="0"
                       Text="{Binding ElementName=slider, Path=Value}" />
                        <Slider Grid.Row="1" Name="slider" Width="120"
                      Minimum="1" Maximum="12"
                      Value="{Binding Mode=TwoWay,
                              RelativeSource={RelativeSource TemplatedParent},
                              Path=Value}"/>
                    </Grid>
    
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    • 复制了放置在 MyControl.cs 中的 C#。整个文件看起来像:-

使用 System.Windows; 使用 System.Windows.Controls;

namespace SilverlightApplication1
{
    public class MyControl : Control
    {
        public MyControl()
        {
            this.DefaultStyleKey = typeof(MyControl);
        }

        public static readonly DependencyProperty ValueProperty =
  DependencyProperty.Register("Value",
  typeof(double),
  typeof(MyControl),
  new PropertyMetadata(0d, OnValueChanged));

        public double Value
        {
            get { return (double)base.GetValue(ValueProperty); }
            set { base.SetValue(ValueProperty, value); }
        }

        private static void OnValueChanged(DependencyObject source,
                                           DependencyPropertyChangedEventArgs e)
        {
            MyControl myControl = (MyControl)source;
            myControl.OnValueChanged((double)e.OldValue, (double)e.NewValue);
        }

        protected virtual void OnValueChanged(double oldValue, double newValue)
        {
            double coercedValue = CoerceValue(newValue);
            if (coercedValue != newValue)
            {
                this.Value = coercedValue;
            }
        }

        private double CoerceValue(double value)
        {
            double limit = 7;
            if (value > limit)
            {
                return limit;
            }
            return value;
        }

    }
}
  • 将 MyControl 的实例添加到 MainPage.xaml,现在看起来像:-

    <UserControl x:Class="SilverlightApplication1.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:SilverlightApplication1"
        mc:Ignorable="d"
        d:DesignHeight="300" d:DesignWidth="400">
    
        <Grid x:Name="LayoutRoot" Background="White">
            <local:MyControl />
         </Grid>
    
     </UserControl>
    
  • 运行解决方案,工作正常。

【讨论】:

  • 好的,现在我已经完成了,就像你写的那样。我添加了“Silverlight Templatd Control”,复制了所有代码。不幸的是我仍然有这个问题。好奇-.-
  • 有点好奇。原因似乎是调试器和 Opera 浏览器?!我曾经在使用 VS 调试时在 Opera 上测试过该程序。从来没有,真的从来没有,没有。一旦我断开调试器,它就运行良好。在 Firefox 中,它每次都有效。感谢您的帮助:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-27
  • 1970-01-01
  • 1970-01-01
  • 2018-06-15
  • 2016-08-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多