【问题标题】:WPF button property on user control not showing properties in property pane用户控件上的 WPF 按钮属性未在属性窗格中显示属性
【发布时间】:2016-06-14 19:11:36
【问题描述】:

这几天我一直在苦苦挣扎,我似乎找不到任何适合我的问题的信息。

所以,我有这个工具栏用户控件,旨在放入应用程序中。此工具栏有一个公开的属性,称为“FullExtentButton”,它是对按钮的引用。我想要的是在工具栏用户控件的设计器属性窗格中公开此按钮的属性,以便开发人员可以直接从设计器设置属性。

在 WinForms 中,这很容易做到。 WPF,没有那么多(除非我只是盲人)。

在我的工具条码中:

[Category("Standard Buttons")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public MyToolbarButton FullExtentButton
{
    get;
    private set;
}

这个值是在用户控件的构造函数中设置的:

public MyToolbar()
{
    InitializeComponent();

    FullExtentButton = new MyToolbarButton("FullExtent", "/Utilities;component/Resources/full_extent_16x16.png");
}

按钮本身很简单:

public class MyToolbarButton
    : Freezable
{
    #region Dependency Properties.
    /// <summary>
    /// Dependency property for the <see cref="IsVisible"/> property.
    /// </summary>
    public static DependencyProperty IsVisibleProperty =     DependencyProperty.Register("IsVisible", typeof(bool), typeof(MyToolbarButton),
                                                                                                 new FrameworkPropertyMetadata(true,
                                                                                                                           FrameworkPropertyMetadataOptions
                                                                                                                           .BindsTwoWayByDefault, Visible_Changed));
/// <summary>
/// Dependency property for the <see cref="IsEnabled"/> property.
/// </summary>
public static DependencyProperty IsEnabledProperty = DependencyProperty.Register("IsEnabled", typeof(bool), typeof(MyToolbarButton),
                                                                                 new FrameworkPropertyMetadata(true,
                                                                                                               FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, Enabled_Changed));

/// <summary>
/// Dependency property for the <see cref="ToolTip"/> property.
/// </summary>
public static DependencyProperty ToolTipProperty = DependencyProperty.Register("ToolTip", typeof(string), typeof(MyToolbarButton),
                                                                                 new FrameworkPropertyMetadata(string.Empty,
                                                                                                               FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, ToolTip_Changed));

/// <summary>
/// Dependency property for the <see cref="Glyph"/> property.
/// </summary>
public static DependencyProperty GlyphProperty = DependencyProperty.Register("Glyph", typeof(ImageSource), typeof(MyToolbarButton),
                                                                                 new FrameworkPropertyMetadata(null,
                                                                                                               FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, Glyph_Changed));

/// <summary>
/// Dependency property for the <see cref="ID"/> property.
/// </summary>
public static DependencyProperty IDProperty = DependencyProperty.Register("ID", typeof(string), typeof(MyToolbarButton),
                                                                          new FrameworkPropertyMetadata(string.Empty,
                                                                                                        FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

/// <summary>
/// Dependency property for the <see cref="ClickedCommand"/> property.
/// </summary>
public static DependencyProperty ClickedCommandProperty = DependencyProperty.Register("ClickedCommand", typeof(IMyRelayCommand<string>), 
    typeof(MyToolbarButton),
    new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
#endregion

#region Variables.
// The default image source for the button glyph.
private readonly Uri _defaultImageSource;
#endregion

#region Properties.
/// <summary>
/// Property to set or return the command to execute when the button is clicked.
/// </summary>
public IMyRelayCommand<string> ClickedCommand
{
    get
    {
        return (IMyRelayCommand<string>)GetValue(ClickedCommandProperty);
    }
    set
    {
        SetValue(ClickedCommandProperty, value);
    }
}


/// <summary>
/// Property to set or return the ID of the button.
/// </summary>
public string ID
{
    get
    {
        object value = GetValue(IDProperty);

        return value == null ? string.Empty : value.ToString();
    }
    set
    {
        SetValue(IDProperty, value);
    }
}

/// <summary>
/// Property to set or return the glyph for this button.
/// </summary>
public ImageSource Glyph
{
    get
    {
        return GetValue(GlyphProperty) as ImageSource;
    }
    set
    {
        SetValue(GlyphProperty, value);
    }
}

/// <summary>
/// Property to set or return the tool tip for the button.
/// </summary>
public string ToolTip
{
    get
    {
        object value = GetValue(ToolTipProperty);

        return value == null ? string.Empty : value.ToString();
    }
    set
    {
        SetValue(ToolTipProperty, value);
    }
}

/// <summary>
/// Property to set or return whether the button is visible or not.
/// </summary>
public bool IsVisible
{
    get
    {
        return (bool)GetValue(IsVisibleProperty);
    }
    set
    {
        SetValue(IsVisibleProperty, value);
    }
}

/// <summary>
/// Property to set or return whether the button is enabled or not.
/// </summary>
public bool IsEnabled
{
    get
    {
        return (bool)GetValue(IsEnabledProperty);
    }
    set
    {
        SetValue(IsEnabledProperty, value);
    }
}
#endregion

#region Methods.
/// <summary>
/// Function to handle a change to the <see cref="GlyphProperty"/>.
/// </summary>
/// <param name="sender">The sender of the event.</param>
/// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private static void Glyph_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
    // TODO
}

/// <summary>
/// Function to handle a change to the <see cref="IsVisibleProperty"/>.
/// </summary>
/// <param name="sender">The sender of the event.</param>
/// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private static void Visible_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
    // TODO
}

/// <summary>
/// Function to handle a change to the <see cref="IsEnabledProperty"/>.
/// </summary>
/// <param name="sender">The sender of the event.</param>
/// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private static void Enabled_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
    // TODO
}

/// <summary>
/// When implemented in a derived class, creates a new instance of the <see cref="T:System.Windows.Freezable" /> derived class.
/// </summary>
/// <returns>The new instance.</returns>
protected override Freezable CreateInstanceCore()
{
    return new MyToolbarButton();
}
#endregion

#region Constructor/Finalizer.
/// <summary>
/// Initializes a new instance of the <see cref="MyToolbarButton"/> class.
/// </summary>
/// <param name="buttonID">The ID of the button being clicked.</param>
/// <param name="defaultImageSource">The default image source URI for the glyph used by the button.</param>
internal MyToolbarButton(string buttonID, string defaultImageSource)
{
    ID = buttonID;
    IsVisible = true;
    IsEnabled = true;
    ToolTip = string.Empty;

    if (!string.IsNullOrWhiteSpace(defaultImageSource))
    {
        _defaultImageSource = new Uri(defaultImageSource, UriKind.Relative);
    }
}

/// <summary>
/// Initializes a new instance of the <see cref="MyToolbarButton"/> class.
/// </summary>
public MyToolbarButton()
{
    // This is here to keep the XAML designer from complaining.         
}
#endregion

但是,当我在 XAML 设计器中查看我的用户控件上的按钮属性并展开其属性时,我得到了以下信息:

如您所见,XAML 设计器中该属性下没有任何属性。我想要的是让该按钮的属性出现在“FullExtentsButton”属性下,以便我的开发人员可以修改属性,但 能够创建/删除已经存在的实例。

我尝试将我的 UserControl 上的 FullExtentButton 属性设置为 DependencyProperty,但这并没有解决任何问题。

这是我们希望跨应用程序使用的标准工具栏的一部分,因此强制一致性对我们来说非常重要。此外,这将使我们的开发人员能够专注于应用程序的其他部分,而不是一遍又一遍地重新实现相同的事情(这是我们现在必须做的)。

也就是说,我在这里束手无策,我做错了什么?

【问题讨论】:

  • 我这样做的方法是创建包含小部分的完整用户控件,例如 MyToolBar Button 是用户控件而不是可冻结的。这不仅允许道具显示在属性页上,还可以将控件拖到任何父控件中。在您的情况下,您将有两个用户控件 1) MyToolBar 和 2) MyToolBarButton,将 MyToolbarButton 拖到 MyToolbar 中,属性应该会显示出来。
  • 这就是我所说的遏制。 “优先组合胜于继承”一旦你拨入这个概念,它就非常酷!
  • 我尝试使用 UserControl,但结果相同。这样做的目的是使按钮成为工具栏的永久部分,即不允许用户添加或删除它。这意味着是一个标准工具栏,它是拖放到绑定到视图模型的标准按钮的命令。我们这样做是为了让我们的开发人员不必为自己做额外的工作,并减少使用这些功能所需的时间(而且它提供了将要使用的应用程序之间的一致性)。

标签: c# wpf xaml user-controls dependency-properties


【解决方案1】:

使用这段代码,我必须对其进行一些更改才能编译......

/// <summary>
/// Interaction logic for MyToolBarButton.xaml
/// </summary>
public partial class MyToolBarButton : UserControl
{
    public MyToolBarButton()
    {
        InitializeComponent();
    }
      #region Dependency Properties.
    /// <summary>
    /// Dependency property for the <see cref="IsVisible"/> property.
    /// </summary>
    public static DependencyProperty IsVisibleProperty = DependencyProperty.Register("IsVisible", typeof(bool), typeof(MyOldToolBarButton),
                                                                                                 new FrameworkPropertyMetadata(true,
                                                                                                                           FrameworkPropertyMetadataOptions
                                                                                                                           .BindsTwoWayByDefault, Visible_Changed));
    /// <summary>
    /// Dependency property for the <see cref="IsEnabled"/> property.
    /// </summary>
    public static DependencyProperty IsEnabledProperty = DependencyProperty.Register("IsEnabled", typeof(bool), typeof(MyOldToolBarButton),
                                                                                     new FrameworkPropertyMetadata(true,
                                                                                                                   FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, Enabled_Changed));

    /// <summary>
    /// Dependency property for the <see cref="ToolTip"/> property.
    /// </summary>
    public static DependencyProperty ToolTipProperty = DependencyProperty.Register("ToolTip", typeof(string), typeof(MyOldToolBarButton),
                                                                                     new FrameworkPropertyMetadata(string.Empty,
                                                                                                                   FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                                                                                                                      new PropertyChangedCallback(ToolTipPropertyChanged)));

    private static void ToolTipPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        throw new NotImplementedException();
    }



    /// <summary>
    /// Dependency property for the <see cref="Glyph"/> property.
    /// </summary>
    public static DependencyProperty GlyphProperty = DependencyProperty.Register("Glyph", typeof(ImageSource), typeof(MyOldToolBarButton),
                                                                                     new FrameworkPropertyMetadata(null,
                                                                                                                   FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, Glyph_Changed));

    /// <summary>
    /// Dependency property for the <see cref="ID"/> property.
    /// </summary>
    public static DependencyProperty IDProperty = DependencyProperty.Register("ID", typeof(string), typeof(MyOldToolBarButton),
                                                                              new FrameworkPropertyMetadata(string.Empty,
                                                                                                            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

    /// <summary>
    /// Dependency property for the <see cref="ClickedCommand"/> property.
    /// </summary>
    public static DependencyProperty ClickedCommandProperty = DependencyProperty.Register("ClickedCommand", typeof(string),
        typeof(MyOldToolBarButton),
        new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
    #endregion

    #region Variables.
    // The default image source for the button glyph.
    public Uri _defaultImageSource { private set; get; }
    #endregion

    #region Properties.



    /// <summary>
    /// Property to set or return the ID of the button.
    /// </summary>

    [Category("Configuration")]
    public string ID
    {
        get
        {
            object value = GetValue(IDProperty);

            return value == null ? string.Empty : value.ToString();
        }
        set
        {
            SetValue(IDProperty, value);
        }
    }

    /// <summary>
    /// Property to set or return the glyph for this button.
    /// </summary>

    [Category("Configuration")]
    public ImageSource Glyph
    {
        get
        {
            return GetValue(GlyphProperty) as ImageSource;
        }
        set
        {
            SetValue(GlyphProperty, value);
        }
    }

    /// <summary>
    /// Property to set or return the tool tip for the button.
    /// </summary>
    /// 

    [Category("Configuration")]
    public string ToolTip
    {
        get
        {
            object value = GetValue(ToolTipProperty);

            return value == null ? string.Empty : value.ToString();
        }
        set
        {
            SetValue(ToolTipProperty, value);
        }
    }

    /// <summary>
    /// Property to set or return whether the button is visible or not.
    /// </summary>
    /// 
    [Category("Configuration")]
    public bool IsVisible
    {
        get
        {
            return (bool)GetValue(IsVisibleProperty);
        }
        set
        {
            SetValue(IsVisibleProperty, value);
        }
    }

    /// <summary>
    /// Property to set or return whether the button is enabled or not.
    /// </summary>
    /// 
    [Category("Configuration")]
    public bool IsEnabled
    {
        get
        {
            return (bool)GetValue(IsEnabledProperty);
        }
        set
        {
            SetValue(IsEnabledProperty, value);
        }
    }
    #endregion

    #region Methods.
    /// <summary>
    /// Function to handle a change to the <see cref="GlyphProperty"/>.
    /// </summary>
    /// <param name="sender">The sender of the event.</param>
    /// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
    private static void Glyph_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        // TODO
    }

    /// <summary>
    /// Function to handle a change to the <see cref="IsVisibleProperty"/>.
    /// </summary>
    /// <param name="sender">The sender of the event.</param>
    /// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
    private static void Visible_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        // TODO
    }

    /// <summary>
    /// Function to handle a change to the <see cref="IsEnabledProperty"/>.
    /// </summary>
    /// <param name="sender">The sender of the event.</param>
    /// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
    private static void Enabled_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        // TODO
    }

    /// <summary>
    /// When implemented in a derived class, creates a new instance of the <see cref="T:System.Windows.Freezable" /> derived class.
    /// </summary>
    /// <returns>The new instance.</returns>
    protected  Freezable CreateInstanceCore()
    {
        return new MyOldToolBarButton();
    }
    #endregion

    #region Constructor/Finalizer.
    /// <summary>
    /// Initializes a new instance of the <see cref="MyOldToolBarButton"/> class.
    /// </summary>
    /// <param name="buttonID">The ID of the button being clicked.</param>
    /// <param name="defaultImageSource">The default image source URI for the glyph used by the button.</param>
    internal void MyOldToolBarButton(string buttonID, string defaultImageSource)
    {
        ID = buttonID;
        IsVisible = true;
        IsEnabled = true;
        ToolTip = string.Empty;

        if (!string.IsNullOrWhiteSpace(defaultImageSource))
        {
            _defaultImageSource = new Uri(defaultImageSource, UriKind.Relative);
        }
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="MyOldToolBarButton"/> class.
    /// </summary>
    public void MyOldToolBarButton()
    {
        // This is here to keep the XAML designer from complaining.         
    }
    #endregion
}

并将其添加到另一个“父”控件...属性如下所示:

这是你要找的吗?

【讨论】:

  • 不完全是。我想要的是让这些属性显示在“FullExtents”属性下的“MyToolbar”上。如果我使用“新建”按钮创建按钮的新实例,则可以执行此操作,但是当我在工具栏构造函数中创建 FullExtents 按钮的实例时,我会得到我之前提到的结果。基本上,该按钮应显示为“MyToolbar”用户控件上的一个属性,并且屏幕截图中的这些属性应显示在其下方。
  • 为了更好地说明我的问题,我上传了一张新图片,在主帖中显示了完整的属性窗格。希望这将有助于消除我的帖子中的任何困惑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-01
  • 1970-01-01
  • 2011-01-20
  • 1970-01-01
相关资源
最近更新 更多