例如我有两个类:
class SomeClass {
public decimal Value1 => ...;
public decimal Value2 => ...;
}
class SomeClassWrapper {
private readonly SomeClass someClass;
public decimal Value1 => someClass.Value1;
public decimal Value2 => someClass.Value2;
public decimal Delta => someClass.Value2 - someClass.Value1;
public SomeClassWrapper(SomeClass someClass) {...}
}
SomeClass
通过第三方代码传递给我的DataTemplate
。但我需要使用SomeClassWrapper
。
那么,如何在xaml中将SomeClass
转换为SomeClassWrapper
?
答案 0 :(得分:0)
您可以使用ObjectDataProvider
创建ObjectType="{x:Type local:SomeClassWrapper}
。然后将此ObjectDataProvider
设置为DataContext
。
不幸的是,没有简单的方法将DataContext传递给此ObjectDataProvider
。有一个黑客描述here。
您无法将DataContext
传递给ObjectDataProvider
,但您可以通过特殊的代理类进行此操作。
public class Proxy : Freezable {
public static readonly DependencyProperty DataProperty = DependencyProperty.Register( "Data", typeof( object ), typeof( Proxy ), new UIPropertyMetadata() );
public object Data {
get { return GetValue( DataProperty ); }
set { SetValue( DataProperty, value ); }
}
protected override Freezable CreateInstanceCore() {
return new Proxy();
}
}
public class ProxyStaticResource : StaticResourceExtension {
public override object ProvideValue(IServiceProvider serviceProvider) {
var proxy = (Proxy) base.ProvideValue( serviceProvider );
return proxy.Data;
}
}
<local:Proxy x:Key="DataContextProxy" Data="{Binding}" />
<Grid.Resources>
<ObjectDataProvider x:Key="TooltipInfo" ObjectType="{x:Type local:TooltipInfo}">
<ObjectDataProvider.ConstructorParameters>
<local:ProxyStaticResource ResourceKey="DataContextProxy" />
</ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>
</Grid.Resources>
<Grid.DataContext>
<StaticResource ResourceKey="TooltipInfo" />
</Grid.DataContext>
也许有一种更简单的方法?
答案 1 :(得分:0)
可能最简单的方法是使用IValueConverter
。
[ValueConversion( typeof( SomeClass ), typeof( SomeClassWrapper ) )]
public class SomeClassWrapperConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
if (value == null) throw new ArgumentNullException( nameof( value ) );
if (value is SomeClass == false) throw new ArgumentException( $"Value ({value?.GetType().Name}) is invalid" );
if (targetType != typeof( object )) throw new ArgumentException( $"Target type ({targetType.Name}) is invalid" );
return new SomeClassWrapper ( (SomeClass) value );
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}
}
<SomeClassWrapperConverter x:Key="SomeClassWrapperConverter" />
<Grid DataContext="{Binding Converter={StaticResource SomeClassWrapperConverter}}" />
答案 2 :(得分:0)
更方便的方法是使用MarkupExtension
。
public class DataContextConverter : MarkupExtension {
public Type TargetType { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider) {
if (TargetType == null) throw new ArgumentNullException( nameof( TargetType ) );
if (serviceProvider == null) throw new ArgumentNullException( nameof( serviceProvider ) );
var targetProvider = (IProvideValueTarget) serviceProvider.GetService( typeof( IProvideValueTarget ) );
if (targetProvider == null) throw new ArgumentNullException( nameof( targetProvider ) );
if (targetProvider.TargetObject is DependencyObject == false) return this; // deferral mechanism
var @object = (FrameworkElement) targetProvider.TargetObject;
return Activator.CreateInstance( TargetType, @object.DataContext );
}
}
<Grid DataContext="{local:DataContextConverter TargetType='local:SomeClassWrapper'}" />