繁体   English   中英

通过xaml中的依赖属性公开初始化对象的内部属性

[英]Expose inner properties of initialized object via dependancy property in xaml

我有从Control派生的类,它在UserControl 所以我的UserControl是用于绑定以及xaml所有操作的连接层。

代码如下:

public partial class CombinedControl: UserControl{}
public class DerivedControl:   MainControl
{
    public int ExampleProp{get; set;}
}

我想做的是在xaml中访问MainControl属性。 我在CombinedControl中有它的实例,并且可以通过DependancyProperty公开对象本身。

public DerivedControl Instance
{
    get
    {
        return (DerivedControl)GetValue(InstanceProperty); 
    }
    set
    { 
       SetValue(InstanceProperty, value);   
    }
 }

public static readonly DependencyProperty InstanceProperty=
        DependencyProperty.Register("Instance", typeof(DerivedControl), typeof(CombinedControl));

我的目标<NameSpaceName:CombinedControl Instance.ExampleProp = "10"/>

问题 :如何在xaml中访问和更改初始化的对象属性?

由于不能使用常规的元素/属性级别的语法,因此可以使用Blend行为来将CombinedControl上的Instance属性作为目标,并将其ExampleProp属性设置为ExampleProp任何值。 这需要添加对System.Windows.Interactivity的引用,该引用是Blend SDK(Visual Studio附带)的一部分。 首先是主要行为:

using System;
using System.ComponentModel;
using System.Reflection;
using System.Windows;
using System.Windows.Interactivity;

// Sets properties on targeted items via XAML.
public class SetPropertyBehavior : Behavior<FrameworkElement>
{
    // Name of the property we want to set on our target.
    public static DependencyProperty PropertyNameProperty =
        DependencyProperty.Register( "PropertyName", typeof( string ), typeof( SetPropertyBehavior ),
        new PropertyMetadata( OnTargetPropertyOrValueChanged ) );

    public string PropertyName
    {
        get { return (string)GetValue( PropertyNameProperty ); }
        set { SetValue( PropertyNameProperty, value ); }
    }

    // Value of the property we want to set.
    public static DependencyProperty PropertyValueProperty =
        DependencyProperty.Register( "PropertyValue", typeof( object ), typeof( SetPropertyBehavior ),
        new PropertyMetadata( OnTargetPropertyOrValueChanged ) );

    public object PropertyValue
    {
        get { return GetValue( PropertyValueProperty ); }
        set { SetValue( PropertyValueProperty, value ); }
    }

    // Target object that has the property we want to set. If this is null, the behavior's
    // associated object will be the target instead.
    public static DependencyProperty TargetProperty =
        DependencyProperty.Register( "Target", typeof( object ), typeof( SetPropertyBehavior ),
        new PropertyMetadata( OnTargetPropertyOrValueChanged ) );

    public object Target
    {
        get { return GetValue( TargetProperty ); }
        set { SetValue( TargetProperty, value ); }
    }

    protected override void OnAttached()
    {
        UpdateTargetProperty();
    }

    private static void OnTargetPropertyOrValueChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
    {
        var behavior = d as SetPropertyBehavior;
        if( behavior != null )
            behavior.UpdateTargetProperty();
    }

    private void UpdateTargetProperty()
    {
        // Ensure we have a property name and target to work with.
        if( string.IsNullOrEmpty( this.PropertyName ) )
            return;

        var target = this.Target ?? this.AssociatedObject;
        if( target == null )
            return;

        // Make sure our property is actually on our target.
        var targetType = target.GetType();
        PropertyInfo propInfo = targetType.GetProperty( this.PropertyName,
            BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic );

        if( propInfo == null )
            return;

        // Try to convert the string from the XAML to a value the target property can store.
        TypeConverter converter = TypeDescriptor.GetConverter( propInfo.PropertyType );
        object propValue = null;
        try
        {
            if( converter.CanConvertFrom( this.PropertyValue.GetType() ) )
                propValue = converter.ConvertFrom( this.PropertyValue );
            else
                propValue = converter.ConvertFrom( this.PropertyValue.ToString() );
        }
        catch( Exception )
        {
            // Do whatever is appropriate in your case.
            propValue = null;
        }

        propInfo.SetValue( target, propValue );
    }
}

然后,根据对您设置ExampleProp值最有意义的ExampleProp ,可以通过XAML添加行为。 例如,如果您在XAML内为CombinedControl添加了行为,则可能看起来像这样:

<UserControl x:Class="NameSpaceName.CombinedControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:NameSpaceName"
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
             x:Name="Root">

    <i:Interaction.Behaviors>
        <local:SetPropertyBehavior Target="{Binding Instance, ElementName=Root}" PropertyName="ExampleProp" PropertyValue="10"/>
    </i:Interaction.Behaviors>

    <!-- Rest of control here -->
</UserControl>

如果您想通过托管您的CombinedControl的任何父项的XAML进行此操作,则可以执行以下操作(以基本的WPF Window为例):

<Window x:Class="NameSpaceName.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:NameSpaceName"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        Title="MainWindow" Height="350" Width="525">

    <i:Interaction.Behaviors>
        <local:SetPropertyBehavior Target="{Binding Instance, ElementName=myCombinedControl}" PropertyName="ExampleProp" PropertyValue="10"/>
    </i:Interaction.Behaviors>

    <Grid>
        <local:CombinedControl x:Name="myCombinedControl"/>
    </Grid>
</Window>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM