为什么我的自定义用户控件属性值和在XAML中设置的值不匹配?

4

背景


如标题所述,我有一个自定义的用户控件。我正在使用Silverlight 4,但我相信这也适用于WPF。目标是创建一个控件,让开发人员可以选择仅显示他们想要在特定页面上显示的控件部分,以及格式化对齐控件备用文本方向属性。

要显示的部分包括:

  • Country
  • SubdivisionCategory(州、地区、外围地区)
  • SubdivisionCensusRegion(东北、南部、中西部、西部)
  • SubdivisionCensusDivision(东北中部、东南中部等)
  • Subdivision

我只是尝试访问当开发人员在XAML中创建此控件的实例时设置的属性值。我为每个属性设置了自定义的DependencyProperty对象,我认为这些对象都是为此目的而设的。


问题


我的问题在于,在SetMargins()期间,所有的this.ShowXxx属性都等于在DependencyProperty.Register方法签名的new PropertyMetadata(true)部分设置的值。因此,边距没有被正确设置。


问题


如何获取this.ShowXxx属性或我在XAML中设置的任何其他属性的初始值?


代码


以下是XAML标记的示例:

<local:CountryAndSubdivisionFilter 
    x:Name="ReportSettingsCountryAndSubdivisionFilter"
    Orientation="Horizontal"
    CountryFormat="Name"
    SubdivisionFormat="Name"
    ShowCountry="False"
    ShowSubdivisionCategory="False"
    ShowSubdivisionCensusRegion="False"
    ShowSubdivisionCensusDivision="True"
    ShowSubdivision="True"
    SubdivisionCensusDivisionText="Region"
    SubdivisionText="State"
    Margin="0,15,0,0" />

以下是“ShowCountry”属性的示例:
#region ShowCountry
public static readonly DependencyProperty ShowCountryProperty = DependencyProperty.Register
(
    "ShowCountry",
    typeof(bool),
    typeof(CountryAndSubdivisionFilter),
    new PropertyMetadata(true)
);
public bool ShowCountry
{
    get
    {
        return (bool) GetValue(ShowCountryProperty);
    }
    set
    {
        SetValue(ShowCountryProperty, value);

        this.CountryStackPanel.Visibility = value ? Visibility.Visible : Visibility.Collapsed;
        this.SetMargins();
    }
}
#endregion

这里是SetMargins()方法:
private void SetMargins()
{
    this.CountryStackPanel.Margin = new Thickness(0);
    this.SubdivisionCategoryStackPanel.Margin = new Thickness(0);
    this.SubdivisionCensusRegionStackPanel.Margin = new Thickness(0);
    this.SubdivisionCensusDivisionStackPanel.Margin = new Thickness(0);
    this.SubdivisionStackPanel.Margin = new Thickness(0);

    var spList = new List<StackPanel>();

    if (this.ShowCountry)
        spList.Add(this.CountryStackPanel);

    if (this.ShowSubdivisionCategory)
        spList.Add(this.SubdivisionCategoryStackPanel);

    if (this.ShowSubdivisionCensusRegion)
        spList.Add(this.SubdivisionCensusRegionStackPanel);

    if (this.ShowSubdivisionCensusDivision)
        spList.Add(this.SubdivisionCensusDivisionStackPanel);

    if (this.ShowSubdivision)
        spList.Add(this.SubdivisionStackPanel);

    int spIndex = 1;
    foreach(var sp in spList)
    {
        var i = (spIndex < spList.Count) ? 15 : 0;
        var j = (spIndex == 1) ? 0 : 15;

        sp.Margin = (this.Orientation == Orientation.Horizontal)
                        ? new Thickness(0, 0, i, 0) 
                        : new Thickness(0, j, 0, 0);

        spIndex++;
    }
}
1个回答

4

回答


对于我上面的具体示例,我所要做的是创建一个名为OnShowCountryPropertyChangedPropertyChangedCallback,然后从那里将属性设置为NewValue,最初这个值是在XAML中分配的值。

为了连接这个回调函数,我只需要更新我的DependencyPropertyPropertyMetadata Constructor,将我的回调函数引用添加到默认值中。

旧签名:new PropertyMetadata(true)

新签名:new PropertyMetadata(true, OnShowCountryPropertyChanged)

完成这两件事之后,在我的SetMargins()方法访问属性的getter时,XAML值就被使用了。


更新代码


#region ShowCountry
public static readonly DependencyProperty ShowCountryProperty = DependencyProperty.Register
(
    "ShowCountry",
    typeof(bool),
    typeof(CountryAndSubdivisionFilter),
    new PropertyMetadata(true, OnShowCountryPropertyChanged)
);
public bool ShowCountry
{
    get
    {
        return (bool) GetValue(ShowCountryProperty);
    }
    set
    {
        SetValue(ShowCountryProperty, value);

        this.CountryStackPanel.Visibility = value ? Visibility.Visible : Visibility.Collapsed;
        this.SetMargins();
    }
}
private static void OnShowCountryPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var ctrl = d as CountryAndSubdivisionFilter;
    ctrl.ShowCountry = (bool) e.NewValue;
}
#endregion

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接