-1

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

    <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”,它是空的。

我已经用谷歌搜索了这个问题,但似乎其他人都无法将值绑定到属性,我只想能够在 XAML 中将属性设置为 0-5 之间的 int。

4

2 回答 2

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)
        {
            // ....
        }
    }
}
于 2017-11-29T14:18:37.300 回答
2

它不是空的,它是零。

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

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

<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 事件,但“更好”的方法是使用依赖属性上的 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;
    }
}
于 2017-11-29T14:18:51.690 回答