2017-08-18 10 views
4

私はDevExpressのWPFツリーリストビューで作業しています。アイテムソースとして使用されているオブジェクトのプロパティの名前変更に関するより一般的な問題だと思いました。ツリーリストビューでは、ParentFieldNameとKeyFieldName(ツリーの構造を決定する)を指定する必要があります。これらのフィールドは文字列です。nameofに相当するXAMLはありますか?

これにより、コードのリファクタリングに関する問題が発生しました。たとえば、私がItemSourceとして使用しているオブジェクトのプロパティの名前を変更すると、ParentFieldNameとKeyFieldNameがプロパティ名と同期しなくなったため、ツリービューが破損します。私はビューにプロパティ名を表示するためにnameofを使用するビューモデル "ParentFieldName"と "KeyFieldName"でプロパティを作成することでこの問題を回避しました。ここで

は、コントロールの削減バージョンです:

<UserControl 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"    
      d:DesignHeight="300" d:DesignWidth="300"> 
     <UserControl.DataContext> 
      <ViewModel /> 
     </UserControl.DataContext> 
     <dxg:TreeListControl AutoGenerateColumns="AddNew" 
         EnableSmartColumnsGeneration="True" ItemsSource="{Binding Results}"       
         SelectionMode="Row"> 
      <dxg:TreeListControl.View> 
       <dxg:TreeListView         
           ParentFieldName="{Binding ParentIdFieldName}" KeyFieldName="{Binding NodeIdFieldName}" 
           ShowHorizontalLines="False" ShowVerticalLines="False" 
           ShowNodeImages="True"/> 
      </dxg:TreeListControl.View> 
     </dxg:TreeListControl> 
    </UserControl> 

とのviewmodel:

using DevExpress.Mvvm;  

public sealed class ViewModel : ViewModelBase 
{ 
    public string ParentIdFieldName => nameof(TreeNode.ParentId); 

    public string NodeIdFieldName => nameof(TreeNode.NodeId); 

    public ObservableCollection<TreeNode> Results 
    { 
     get => GetProperty(() => Results); 
     set => SetProperty(() => Results, value); 
    } 
} 

とツリーノード:

public sealed class TreeNode 
{ 
    public int ParentId {get; set;} 
    public int NodeId {get; set;} 
} 

私のソリューションは、うまく動作しますが、Iこれを行うより良い方法があるかどうか疑問に思っていました。たとえば、ビューモデルのこのParentIdFieldNameとNodeIdFieldNameにバインドするのではなく、nameof呼び出しと同等のXAMLでできることはありますか?

私はこれがDevExpressのコントロールの問題として説明できることを認識しています。しかし、私はこれを回避するために慣れてきたアプローチが改善できるかどうかに興味があります。これをXAMLでより簡単な方法で直接実行できる方法はありますか?

私が提供したコードがコンパイルされない場合は、事前にお詫び申し上げます。私は例を提供するために私がかなり作業しているものをかなり減らしました。

答えて

8

カスタムマークアップ拡張を作成できます。

[ContentProperty(nameof(Member))] 
public class NameOfExtension : MarkupExtension 
{ 
    public Type Type { get; set; } 
    public string Member { get; set; } 

    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     if (serviceProvider == null) 
      throw new ArgumentNullException(nameof(serviceProvider)); 

     if (Type == null || string.IsNullOrEmpty(Member) || Member.Contains(".")) 
      throw new ArgumentException("Syntax for x:NameOf is Type={x:Type [className]} Member=[propertyName]"); 

     var pinfo = Type.GetRuntimeProperties().FirstOrDefault(pi => pi.Name == Member); 
     var finfo = Type.GetRuntimeFields().FirstOrDefault(fi => fi.Name == Member); 
     if (pinfo == null && finfo == null) 
      throw new ArgumentException($"No property or field found for {Member} in {Type}"); 

     return Member; 
    } 
} 

使用例:

enter image description here

例えば

関連する問題