簡體   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