自定义属性的字面值为空

时间:2017-11-29 14:12:01

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

我使用用户控件创建了一个标签栏,因为我需要标签栏在多个页面上,因为它会更改当前页面。这意味着标签栏必须通过在正确的图像后面移动一个黑色矩形来显示当前显示的页面。所以我尝试使用一个名为SelectionIndex的自定义属性将选择矩形移动到正确的图像后面,0是Home图像,1是Schedule图像等。下面的代码显示了所选图像应该在的页面上使用的标签栏第二个。

    <Grid>
        <local:TabBar SelectionIndex="1" Margin="0,0,1222,0"/>
    </Grid>

下面的代码由propdp生成,我将属性的名称更改为SelectionIndex。然后我使用Switch-Case来检查属性的值是什么,并更改矩形图像的边距以移动它。

public partial class TabBar : UserControl
{
    public int SelectionIndex
    {
        get { return (int)GetValue(SelectionIndexProperty); }
        set { SetValue(SelectionIndexProperty, value); }
    }

    // Using a DependencyProperty as the backing store for SelectionIndex.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty SelectionIndexProperty =
        DependencyProperty.Register("SelectionIndex", typeof(int), typeof(TabBar), new PropertyMetadata(0));


    public TabBar()
    {
        InitializeComponent();

        switch (SelectionIndex)
        {
            case 0:
                SelectionBox.Margin = new Thickness(0, 10, 0, 0);
                break;
            case 1:
                SelectionBox.Margin = new Thickness(0, 123, 0, 0);
                break;
        }
    }
}

但是,我在switch (SelectionIndex)上设置了一个断点来检查SelectionIndex的值,它是0,但应该是1。 为了自己解决这个问题,我将属性类型从int更改为字符串,这表明SelectionIndex不是“0”,它是null。

我已经用Google搜索了这个问题,但似乎其他所有人都遇到了将值绑定到属性的问题,我只是希望能够在XAML中将属性设置为0-5之间的int。

2 个答案:

答案 0 :(得分:3)

问题是您在构造函数中执行此操作,并在创建控件后在属性上设置值。

您需要在依赖项属性上添加属性更改处理程序,并调用方法来处理更改:

public partial class TabBar : UserControl
{
    ....
    // Using a DependencyProperty as the backing store for SelectionIndex.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty SelectionIndexProperty =
        DependencyProperty.Register("SelectionIndex", typeof(int), typeof(TabBar), new PropertyMetadata(0, propertyChangedCallback: (d,e)=> ((TabBar)d).OnSelectionIndexChanged()));


    public void OnSelectionIndexChanged()
    {
        switch (SelectionIndex)
        {
            // ....
        }
    }
}

答案 1 :(得分:2)

它不为空,它为零。

但是,从狭义上讲,你的麻烦是在构造函数完成之后才分配属性。但更广泛地说,你没有利用WPF让你做事的方式。

在WPF中,这可以在没有太多C#代码的情况下完成。不要使用边距进行定位,使用网格。定位&#34;标记&#34;通过将其Grid.Column属性绑定到SelectedIndex,网格中的边框。尽可能简单,现在你可以调整网格中的项目大小,一切都会神奇地工作。如果你想在第三栏中加入两件事,那么总是更好地说&#34;把这个和第二列放在第三列&#34;而不是&#34;把它放在356个单位偏移&#34;而在其他地方说&#34;把它放在呃......第三列的偏移又是什么?&#34;然后你明年改变设计并忘记更新其中一个。

<Grid>
    <Grid.ColumnDefinitions>
        <!-- Made up width values -->
        <ColumnDefinition Width="100" />
        <ColumnDefinition Width="100" />
        <ColumnDefinition Width="100" />
        <ColumnDefinition Width="100" />
    </Grid.ColumnDefinitions>
    <Border
        Background="DeepSkyBlue"
        Grid.Column="{Binding SelectionIndex, RelativeSource={RelativeSource AncestorType=UserControl}}"
        >
    </Border>
    <Label Grid.Column="0">Click Me</Label>
    <Label Grid.Column="1">No, Click Me</Label>
    <Label Grid.Column="2">Me Me Me!</Label>
    <Label Grid.Column="3">Wahhhh</Label>
</Grid>

<强>然而

如果您想坚持使用原始方法,可以将该switch语句移动到Loaded事件,但更好的&#34;这样做的方法是使用依赖项属性上的PropertyChanged处理程序。这样,只要属性发生变化,您的控件就会适当地响应更改。我们将默认值设为-1,否则将无法调用属性更改处理程序:

public int SelectionIndex
{
    get { return (int)GetValue(SelectionIndexProperty); }
    set { SetValue(SelectionIndexProperty, value); }
}

public static readonly DependencyProperty SelectionIndexProperty =
    DependencyProperty.Register(nameof(SelectionIndex), typeof(int), typeof(TabBar),
        new FrameworkPropertyMetadata(-1, SelectionIndex_PropertyChanged));

protected static void SelectionIndex_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    (d as TabBar).OnSelectionIndexChanged(e.OldValue);
}

private void OnSelectionIndexChanged(object oldValue)
{
    switch (SelectionIndex)
    {
        case 0:
            SelectionBox.Margin = new Thickness(0, 10, 0, 0);
            break;
        case 1:
            SelectionBox.Margin = new Thickness(0, 123, 0, 0);
            break;
    }
}