[英]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.