【问题标题】:WPF :: Custom Control's Dependency Properties Aren't WorkingWPF :: 自定义控件的依赖属性不起作用
【发布时间】:2015-04-07 16:56:56
【问题描述】:

我正在为所见即所得的 HTML 编辑器制作 Ribbon 控件。功能区具有您希望看到的典型粗体、斜体、下划线、FontFamily 等控件。我将重点介绍本示例的 Bold 功能。

我希望 Ribbon 可重用,因此我在控件的代码后面(标准样板代码)中添加了一个依赖属性 (DP) 和关联的属性包装器:

public partial class EditorRibbon: UserControl
{
  public static readonly DependencyProperty IsBoldProperty = 
    DependencyProperty.Register(
     "IsBold", 
     typeof (bool), 
     typeof (EditorRibbon), 
     new PropertyMetadata(default(bool)));

  public bool IsBold
  {
     get { return (bool) GetValue(IsBoldProperty); }
     set { SetValue(IsBoldProperty, value); }
  }
}

...在 XAML 中我有我的 RibbonToggleButton,并且我已将 IsChecked 属性绑定到依赖属性:

<UserControl x:Class="My.EditorRibbon">
  <r:RibbonToggleButton Command="ToggleBold"
                        ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}"
                        SmallImageSource="{StaticResource ToggleBoldIcon}" 
                        IsChecked="{Binding IsBold}" />

</UserControl>

在我的Editor 窗口中,我已将EditorRibbonIsBold 属性绑定到窗口的ViewModel 上的常规属性:

<Window x:class="My.MainWindow>
  <My.EditorRibbon IsBold="{Binding SelectionIsBold}"/>
</Window>

这是SelectionIsBold 属性:

public bool SelectionIsBold
{
  get { return _selection.IsBold(); }
}   

...每当RichTextBox 中的选择发生变化时,我都会引发NotifyPropertyChanged() 事件(在MainWindow 的ViewModel 中):

public class MainWindowViewModel : BaseViewModel 
{
    public MainWindowViewModel(MainWindow window)
    {
       rtb.SelectionChanged += rtb_OnSelectionChanged;
    }

    private void rtb_OnSelectionChanged(object sender, RoutedEventArgs routedEventArgs)
    {
      NotifyPropertyChanged(()=>SelectionIsBold);
    }

}

在我看来,这应该足以在选择更改时更改RibbonToggleButtonIsChecked 状态......但事实并非如此。尽管更改了选择,尽管NotifyPropertyChanged() 按预期触发,SelectionIsBold 属性上的断点(是的,我已取消选择 VS 的“Step Over Property”设置)永远不会命中。在某处,刷新值的请求未正确传播。

在 setter 中设置值后,是否需要在 IsBold 属性上触发 NotifyPropertyChanged()?

【问题讨论】:

  • 你不需要绑定你的命令吗? Command="{Binding ToggleBold}"
  • “rtb_OnSelectionChanged”在哪里
  • @Neil - rtb_OnSelectionChanged 位于包含 RichTextBox 和 EditorRibbon 的窗口中。
  • @ScottNimrod - 不。该命令按原样完美运行。
  • 需要指定 UpdateSourceTrigger 还是指定 Mode 为 TwoWay?

标签: c# wpf xaml dependency-properties


【解决方案1】:

将 IsBold 绑定更改为以下内容

<UserControl x:Class="My.EditorRibbon" x:Name="EditorRibbonInstance">
<r:RibbonToggleButton Command="ToggleBold"
                    ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}"
                    SmallImageSource="{StaticResource ToggleBoldIcon}" 
                    IsChecked="{Binding IsBold, ElementName=EditorRibbonInstance, Mode=TwoWay}" />
</UserControl>

这样您就可以确定绑定将转到控件的属性而不是控件的数据上下文

【讨论】:

  • 我试过了,不高兴 - 有些东西仍然无法正常工作。选择更改时,IsChecked 属性仍未更新。
  • 我忘了添加模式 TwoWay,试试那个
  • 为什么会是 TwoWay? IsChecked 属性不会将其值推送到任何地方——它是严格从选择中读取的。无论哪种方式,它都不起作用。
【解决方案2】:

您必须在 ViewModel 中触发 notifypropertychanged。在 ViewModel 中尝试这样的事情:

 protected void FirePropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }


->>   FirePropertyChanged("SelectionIsBold")

原因是:现在,你的数据上下文是 ViewModel,所有绑定到 ViewModel 必须由 ViewModel 的属性触发

【讨论】:

  • 我将订阅事件和事件处理程序移动到 ViewModel,但仍然没有任何乐趣。我正在更新我的帖子以反映这一点。
  • 我的 NotifyPropertyChanged(()=> SelectionIsBold) 方法就是这样做的,它只是使用反射而不是字符串来获取属性名称。
【解决方案3】:

首先,我以前从未见过将 Window 注入到 ViewModel 中……您是否使用某种 DI 进行注入?

我认为在视图模型上使用选择更改事件不是一个好主意...从我的角度来看,这不是 mvvm...

您是否在某处更新_selection?可能是你总是检查相同的选择?!

【讨论】:

    【解决方案4】:

    您没有正确绑定按钮的命令属性。

    应该反映如下内容:

    Command="{Binding ToggleBold}"
    

    【讨论】:

    • 我不同意。 ToggleBold 命令运行良好。当 CanExecute() 失败时,该按钮会禁用,并且 Execute() 方法会像宣传的那样切换粗体。唯一不起作用的部分是连接 IsChecked 以反映当前选择。
    • 好的。我不知道您可以在没有绑定语法仪式的情况下将字符串值分配给命令属性。
    • 只是让你知道,不是我对你投了反对票。 :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多