我使用以下模式根据具体的模型实例一般性地创建基本视图mdoel的专用实例:
#region Model
public class Model
{
}
public class DerivedModel : Model
{
}
#endregion
#region ViewModel
public abstract class ViewModel
{
public static ViewModel Create(Model model)
{
return (ViewModel)CreateInternal((dynamic) model);
}
private static ViewModel<TModel> CreateInternal<TModel>(TModel model)
{
var viewModel = IoC.Get<ViewModel<DerivedModel>>();
viewModel.Model = model;
return viewModel;
}
public Model Model { get { return GetModel(); } }
internal abstract Model GetModel();
}
public abstract class ViewModel<TModel> : ViewModel where TModel : Model
{
public new TModel Model { get; internal set; }
internal override Model GetModel() { return Model; }
}
[Export(typeof(ViewModel<DerivedModel>))]
/*private*/ class MySpecializedModel : ViewModel<DerivedModel>
{
//specialization
}
#endregion
这个想法是通过MEF实现它们,因此不需要知道conMcete ViewModel Type,并且可以在其他程序集中定义特化并在运行时插入程序。
但是,当我尝试绑定到Model
属性时,我在wpf框架内部的某个地方得到了一个AmbiguousMatchException(实际上,绑定本身并没有失败,但是MeasureOverride中的某些代码试图通过反射访问该属性): / p>
System.Reflection.AmbiguousMatchException occurred
Source=mscorlib
StackTrace:
mscorlib.dll!System.RuntimeType.GetPropertyImpl(string name, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Type returnType, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) + 0x127 bytes
mscorlib.dll!System.Type.GetProperty(string name, System.Reflection.BindingFlags bindingAttr) + 0x1f bytes
PresentationFramework.dll!System.Windows.PropertyPath.GetPropertyHelper(System.Type ownerType, string propertyName) + 0x31 bytes
PresentationFramework.dll!System.Windows.PropertyPath.ResolvePropertyName(string name, object item, System.Type ownerType, object context, bool throwOnError) + 0x8e bytes
PresentationFramework.dll!MS.Internal.Data.PropertyPathWorker.GetInfo(int k, object item, ref MS.Internal.Data.PropertyPathWorker.SourceValueState svs) + 0x3b5 bytes
PresentationFramework.dll!MS.Internal.Data.PropertyPathWorker.ReplaceItem(int k, object newO, object parent) + 0x302 bytes
PresentationFramework.dll!MS.Internal.Data.PropertyPathWorker.UpdateSourceValueState(int k, System.ComponentModel.ICollectionView collectionView, object newValue, bool isASubPropertyChange) + 0xea bytes
PresentationFramework.dll!MS.Internal.Data.ClrBindingWorker.AttachDataItem() + 0x9e bytes
PresentationFramework.dll!System.Windows.Data.BindingExpression.Activate(object item) + 0x10d bytes
PresentationFramework.dll!System.Windows.Data.BindingExpression.AttachToContext(System.Windows.Data.BindingExpression.AttachAttempt attempt) + 0x33a bytes
PresentationFramework.dll!System.Windows.Data.BindingExpression.AttachOverride(System.Windows.DependencyObject target, System.Windows.DependencyProperty dp) + 0xd1 bytes
PresentationFramework.dll!System.Windows.Data.BindingExpressionBase.OnAttach(System.Windows.DependencyObject d, System.Windows.DependencyProperty dp) + 0x38 bytes
PresentationFramework.dll!System.Windows.StyleHelper.GetInstanceValue(System.Windows.UncommonField<System.Collections.Specialized.HybridDictionary[]> dataField, System.Windows.DependencyObject container, System.Windows.FrameworkElement feChild, System.Windows.FrameworkContentElement fceChild, int childIndex, System.Windows.DependencyProperty dp, int i, ref System.Windows.EffectiveValueEntry entry) + 0x1a5 bytes
PresentationFramework.dll!System.Windows.StyleHelper.GetChildValueHelper(System.Windows.UncommonField<System.Collections.Specialized.HybridDictionary[]> dataField, ref MS.Utility.ItemStructList<System.Windows.ChildValueLookup> valueLookupList, System.Windows.DependencyProperty dp, System.Windows.DependencyObject container, MS.Internal.FrameworkObject child, int childIndex, bool styleLookup, ref System.Windows.EffectiveValueEntry entry, out System.Windows.ValueLookupType sourceType, System.Windows.FrameworkElementFactory templateRoot) + 0x4e7 bytes
PresentationFramework.dll!System.Windows.StyleHelper.GetChildValue(System.Windows.UncommonField<System.Collections.Specialized.HybridDictionary[]> dataField, System.Windows.DependencyObject container, int childIndex, MS.Internal.FrameworkObject child, System.Windows.DependencyProperty dp, ref MS.Utility.FrugalStructList<System.Windows.ChildRecord> childRecordFromChildIndex, ref System.Windows.EffectiveValueEntry entry, out System.Windows.ValueLookupType sourceType, System.Windows.FrameworkElementFactory templateRoot) + 0xbc bytes
PresentationFramework.dll!System.Windows.StyleHelper.GetValueFromTemplatedParent(System.Windows.DependencyObject container, int childIndex, MS.Internal.FrameworkObject child, System.Windows.DependencyProperty dp, ref MS.Utility.FrugalStructList<System.Windows.ChildRecord> childRecordFromChildIndex, System.Windows.FrameworkElementFactory templateRoot, ref System.Windows.EffectiveValueEntry entry) + 0x52 bytes
PresentationFramework.dll!System.Windows.StyleHelper.ApplyTemplatedParentValue(System.Windows.DependencyObject container, MS.Internal.FrameworkObject child, int childIndex, ref MS.Utility.FrugalStructList<System.Windows.ChildRecord> childRecordFromChildIndex, System.Windows.DependencyProperty dp, System.Windows.FrameworkElementFactory templateRoot) + 0x78 bytes
PresentationFramework.dll!System.Windows.StyleHelper.InvalidatePropertiesOnTemplateNode(System.Windows.DependencyObject container, MS.Internal.FrameworkObject child, int childIndex, ref MS.Utility.FrugalStructList<System.Windows.ChildRecord> childRecordFromChildIndex, bool isDetach, System.Windows.FrameworkElementFactory templateRoot) + 0x8c bytes
PresentationFramework.dll!System.Windows.FrameworkTemplate.InvalidatePropertiesOnTemplate(System.Windows.DependencyObject container, object currentObject) + 0xcf bytes
PresentationFramework.dll!System.Windows.FrameworkTemplate.HandleBeforeProperties(object createdObject, ref System.Windows.DependencyObject rootObject, System.Windows.DependencyObject container, System.Windows.FrameworkElement feContainer, System.Windows.Markup.INameScope nameScope) + 0x2d bytes
PresentationFramework.dll!System.Windows.FrameworkTemplate.LoadOptimizedTemplateContent.AnonymousMethod__3(object sender, System.Xaml.XamlObjectEventArgs args) + 0x24 bytes
System.Xaml.dll!System.Xaml.XamlObjectWriter.OnBeforeProperties(object value) + 0x46 bytes
System.Xaml.dll!System.Xaml.XamlObjectWriter.Logic_CreateAndAssignToParentStart(MS.Internal.Xaml.Context.ObjectWriterContext ctx) + 0xfe bytes
System.Xaml.dll!System.Xaml.XamlObjectWriter.WriteEndObject() + 0x2ae bytes
System.Xaml.dll!System.Xaml.XamlWriter.WriteNode(System.Xaml.XamlReader reader) + 0x65 bytes
PresentationFramework.dll!System.Windows.FrameworkTemplate.LoadTemplateXaml(System.Xaml.XamlReader templateReader, System.Xaml.XamlObjectWriter currentWriter) + 0x41 bytes
PresentationFramework.dll!System.Windows.FrameworkTemplate.LoadTemplateXaml(System.Xaml.XamlObjectWriter objectWriter) + 0x61 bytes
PresentationFramework.dll!System.Windows.FrameworkTemplate.LoadOptimizedTemplateContent(System.Windows.DependencyObject container, System.Windows.Markup.IComponentConnector componentConnector, System.Windows.Markup.IStyleConnector styleConnector, System.Collections.Generic.List<System.Windows.DependencyObject> affectedChildren, System.Windows.UncommonField<System.Collections.Hashtable> templatedNonFeChildrenField) + 0x259 bytes
PresentationFramework.dll!System.Windows.FrameworkTemplate.LoadContent(System.Windows.DependencyObject container, System.Collections.Generic.List<System.Windows.DependencyObject> affectedChildren) + 0x7b bytes
PresentationFramework.dll!System.Windows.StyleHelper.ApplyTemplateContent(System.Windows.UncommonField<System.Collections.Specialized.HybridDictionary[]> dataField, System.Windows.DependencyObject container, System.Windows.FrameworkElementFactory templateRoot, int lastChildIndex, System.Collections.Specialized.HybridDictionary childIndexFromChildID, System.Windows.FrameworkTemplate frameworkTemplate) + 0xa5 bytes
PresentationFramework.dll!System.Windows.FrameworkTemplate.ApplyTemplateContent(System.Windows.UncommonField<System.Collections.Specialized.HybridDictionary[]> templateDataField, System.Windows.FrameworkElement container) + 0x3b bytes
PresentationFramework.dll!System.Windows.FrameworkElement.ApplyTemplate() + 0x7c bytes
PresentationFramework.dll!System.Windows.FrameworkElement.MeasureCore(System.Windows.Size availableSize) + 0x40 bytes
PresentationCore.dll!System.Windows.UIElement.Measure(System.Windows.Size availableSize) + 0x1cc bytes
PresentationFramework.dll!System.Windows.Controls.Control.MeasureOverride(System.Windows.Size constraint) + 0x60 bytes
PresentationFramework.dll!System.Windows.FrameworkElement.MeasureCore(System.Windows.Size availableSize) + 0x1cc bytes
PresentationCore.dll!System.Windows.UIElement.Measure(System.Windows.Size availableSize) + 0x1cc bytes
PresentationFramework.dll!System.Windows.Controls.Grid.MeasureOverride(System.Windows.Size constraint) + 0x281 bytes
PresentationFramework.dll!System.Windows.FrameworkElement.MeasureCore(System.Windows.Size availableSize) + 0x1cc bytes
PresentationCore.dll!System.Windows.UIElement.Measure(System.Windows.Size availableSize) + 0x1cc bytes
PresentationFramework.dll!System.Windows.Controls.Grid.MeasureCell(int cell, bool forceInfinityV) + 0xe9 bytes
PresentationFramework.dll!System.Windows.Controls.Grid.MeasureCellsGroup(int cellsHead, System.Windows.Size referenceSize, bool ignoreDesiredSizeU, bool forceInfinityV, out bool hasDesiredSizeUChanged) + 0x8a bytes
PresentationFramework.dll!System.Windows.Controls.Grid.MeasureOverride(System.Windows.Size constraint) + 0x3e6 bytes
PresentationFramework.dll!System.Windows.FrameworkElement.MeasureCore(System.Windows.Size availableSize) + 0x1cc bytes
PresentationCore.dll!System.Windows.UIElement.Measure(System.Windows.Size availableSize) + 0x1cc bytes
PresentationFramework.dll!System.Windows.Controls.Grid.MeasureCell(int cell, bool forceInfinityV) + 0xe9 bytes
PresentationFramework.dll!System.Windows.Controls.Grid.MeasureCellsGroup(int cellsHead, System.Windows.Size referenceSize, bool ignoreDesiredSizeU, bool forceInfinityV, out bool hasDesiredSizeUChanged) + 0x8a bytes
PresentationFramework.dll!System.Windows.Controls.Grid.MeasureOverride(System.Windows.Size constraint) + 0x3e6 bytes
PresentationFramework.dll!System.Windows.FrameworkElement.MeasureCore(System.Windows.Size availableSize) + 0x1cc bytes
PresentationCore.dll!System.Windows.UIElement.Measure(System.Windows.Size availableSize) + 0x1cc bytes
PresentationFramework.dll!System.Windows.Controls.Control.MeasureOverride(System.Windows.Size constraint) + 0x60 bytes > Telerik.Windows.Controls.Navigation.dll!Telerik.Windows.Controls.RadTreeViewItem.MeasureOverride(System.Windows.Size availableSize) Line 1537 + 0x28 bytes
...
因此,使用一些搜索继承链的用户定义函数的答案,例如,正如线程AmbiguousMatchException - Type.GetProperty - C# Reflection中提出的那样,不适用于此。
如何实现模式以便我可以从专用的viewmodel类中访问专用的Model
属性,还可以从基本视图模型中访问基本属性?重命名属性看起来很难看,因为它指向同一个对象!