0

我有一个带有自定义 DependencyProperty 的自定义 UserControl。为了更好地了解我是如何使用它的,UserControl 是一个类似向导的控件中的左侧导航指示器。左侧导航控件存在于代表向导中的一个步骤的每个控件中。在左侧导航控件内部,我使用一些转换器切换可见性并设置几个子控件的视觉属性,代码类似于以下内容。我不能使用简单的样式选择器或样式选择转换器,因为无论是否选择了项目,我的 StackPanel 中每一行的整个结构都是不同的。

这是大量代码在我的控件中重复以绑定到单个自定义属性。是否有以下更短的形式版本或更清洁的方式来实现它?

<Polygon
    Visibility="{Binding
    RelativeSource={RelativeSource Mode=FindAncestor,
    AncestorType=UserControl},
    Path=Selected,
    Converter={StaticResource myCustomConverter},
    ConverterParameter='Expected String'}">
...

父视图提供一个属性来自定义子控件:

    <!-- Left Column -->
    <views:LeftNavControl Selected="Item to Select..." />
4

3 回答 3

1

您可以做一些事情,但我不会将它们描述为既不是更清洁/更短的实现方式。MVVM如果您使用一种方法,它们很容易实现。

您可以做的第一件事是摆脱RelativeSource/AncestorType绑定中的 以查找绑定属性的位置。如果您的两个/所有控件(尚不清楚您使用多少个控件)将共享相同的视图模型,您可以将相同的视图模型属性绑定到views:LeftNavControl.Selected,以及所有切换的可见性控件。

您可以做的第二件事是一种更激进的方法,可以清理您的 xaml,它也会使您myCustomConverter过时,但会在您的视图模型中移动一些业务逻辑。这在您有大量Polygons需要可见性切换的 /other 控件时效果最好。您可以在视图模型中有一个StepXVisiblity属性,并且您可以在每次views:LeftNavControl.Selected更改时计算它,并且您的 Polygon(s) xaml 将如下所示:

<Polygon Visibility="{Binding StepXVisiblity}">

上述解释的一个简单示例是:

<StackPanel>
    <TextBox Text="{Binding Step, UpdateSourceTrigger=PropertyChanged}" />
    <TextBlock Text="One" Visibility="{Binding StepOneVisible}" />
    <TextBlock Text="One" Visibility="{Binding StepOneVisible}" />
    <TextBlock Text="Two" Visibility="{Binding StepTwoVisible}" />
    <TextBlock Text="Two" Visibility="{Binding StepTwoVisible}" />
</StackPanel>

视图模型:

public class MyVM : DomainBase
{
    private int step;

    public int Step
    {
        get 
        { 
            return step; 
        }
        set 
        { 
            step = value;
            OnPropertyChanged("Step");
            OnPropertyChanged("StepOneVisible");
            OnPropertyChanged("StepTwoVisible");
        }
    }

    public Visibility StepOneVisible
    {
        get
        {
            return step == 1 ? Visibility.Visible : Visibility.Collapsed;
        }
    }

    public Visibility StepTwoVisible
    {
        get
        {
            return step == 2 ? Visibility.Visible : Visibility.Collapsed;
        }
    }
}
于 2012-06-13T22:27:42.043 回答
0

唯一想到的是创建自己的绑定类,该绑定类派生自基类(它本身是标记扩展),并将所有这些属性设置为您通常使用的默认值。这样,您只需指定非默认值。

于 2012-06-13T22:18:56.920 回答
0

首先,由于您说了一些类似于导航面板的内容,您可能需要考虑使用列表视图或列表框之类的东西,并在绑定到视图模型中的集合时模板化您的项目。但是,由于我不知道您的 Nav 控件的范围,我会假设您的 Nav 控件并不完全适合此方案。

我会建议使用附加属性来实现您所描述的基于单个父属性设置多个属性。将以下内容视为伪代码,因为我尚未对其进行测试:

    public class MagicHelper
    {
        #region Super Property


        public static readonly DependencyProperty SuperProperty =
            DependencyProperty.RegisterAttached(
                "Super", typeof(SecretType), typeof(MagicHelper)
                new PropertyMetadata(-1, SuperChanged));

        // Get
        public static SecretType GetSuper(DependencyObject obj)
        {
            return (SecretType)obj.GetValue(SuperProperty);
        }

        // Set
        public static void SetSuper(DependencyObject obj, SecretType value)
        {
            obj.SetValue(SuperProperty, value);
        }

        // Change Event - make stuff happen here
        public static void SuperChanged(
            DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {

// I am using Polygon here for example but you could use a base class that might cover all your controls
            if (!(obj is Polygon))
                return;


            Polygon pGon = (Polygon)obj;

        // do your thing to pGon here with e.NewValue
        var mySecretInstance = e.NewValue as SecretType;

        if (mySecretInstance.frap)
        {
        pGon.Visibility = Visibility.Collapsed;
        pGon.Background = Brushes.Red;
            }

...
...

        }

}

XAML 是这样的

<UserControl Name="thisControl" 
xmlns:local="yourLibrary">
<Polygon local:MagicHelper.Super="{Binding ElementName=thisControl, Path=Selected"/>
...

于 2012-06-13T23:05:36.287 回答