2014-01-08 4 views
4

GridViewColumn에 대한 부모 (ListView)를 가져 오는 방법이 있습니까?GridViewColumn에 대한 부모 가져 오기

LogicalTreeHelper 및 VisualTreeHelper를 사용해 보았지만 주사위는 사용하지 않았습니다.

나는 - 무슨 - 당신 - 노력이 조금 재미, 그것은하지만 추한 작동하는 그것을 설명 가까이하지 공유 할 수 있습니다

public class Prototype 
{ 
    [Test, RequiresSTA] 
    public void HackGetParent() 
    { 
     var lw = new ListView(); 
     var view = new GridView(); 
     var gvc = new GridViewColumn(); 
     view.Columns.Add(gvc); 
     lw.View = view; 
     var ancestor = new Ancestor<ListView>(); 

     var binding = new Binding 
     { 
      RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(ListView), 1), 
      Converter = new GetAncestorConverter<ListView>(), // Use converter to hack out the parent 
      ConverterParameter = ancestor // conveterparameter used to return the parent 
     }; 
     BindingOperations.SetBinding(gvc, GridViewColumn.WidthProperty, binding); 

     lw.Items.Add(DateTime.Now); // think it cannot be empty for resolve to work 
     ResolveBinding(lw); 
     Assert.AreEqual(lw, ancestor.Instance); 
    } 

    private void ResolveBinding(FrameworkElement element) 
    { 
     element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); 
     element.Arrange(new Rect(element.DesiredSize)); 
     element.UpdateLayout(); 
    } 
} 
public class GetAncestorConverter<T> : IValueConverter 
{ 
    public object Convert(object value, Type type, object parameter, CultureInfo culture) 
    { 
     var ancestor = (Ancestor<T>)parameter; 
     ancestor.Instance = (T)value; 
     return null; 
    } 

    public object ConvertBack(object o, Type type, object parameter, CultureInfo culture) 
    { 
     throw new NotSupportedException(); 
    } 
} 
public class Ancestor<T> 
{ 
    public T Instance { get; set; } 
} 

답변

4

무엇 당신은 불행히도 DependencyObjectInheritanceContext의 내부 속성 뒤에 숨겨져 있으므로 액세스 할 수있는 유일한 방법은 리플렉션을 통한 것입니다. 그래서 당신이 편안하다면이 해결책이 효과적입니다.

public class Prototype 
{ 
    [Test, RequiresSTA] 
    public void HackReflectionGetParent() 
    { 
     var lw = new ListView(); 
     var view = new GridView(); 
     var gvc = new GridViewColumn(); 
     view.Columns.Add(gvc); 
     lw.View = view; 

     var resolvedLw = gvc.GetParents().OfType<ListView>().FirstOrDefault(); 
     Assert.AreEqual(lw, resolvedLw); 
    } 
} 

public static class DependencyObjectExtensions 
{ 
    private static readonly PropertyInfo InheritanceContextProp = typeof (DependencyObject).GetProperty("InheritanceContext", BindingFlags.NonPublic | BindingFlags.Instance); 

    public static IEnumerable<DependencyObject> GetParents(this DependencyObject child) 
    { 
     while (child != null) 
     { 
      var parent = LogicalTreeHelper.GetParent(child); 
      if (parent == null) 
      { 
       if (child is FrameworkElement) 
       { 
        parent = VisualTreeHelper.GetParent(child); 
       } 
       if (parent == null && child is ContentElement) 
       { 
        parent = ContentOperations.GetParent((ContentElement) child); 
       } 
       if (parent == null) 
       { 
        parent = InheritanceContextProp.GetValue(child, null) as DependencyObject; 
       } 
      } 
      child = parent; 
      yield return parent; 
     } 
    } 
} 

다시 2009 년에이 공표 된 약 some discussion 있었다 아무것도 나는 그것이 될 것입니다 의심 때문에 일이 없다. 그 속성은 프레임 워크 내에서 광범위하게 사용되고 다른 프레임 워크 어셈블리에 대해 Friend Visible입니다. 그래서 나는 곧 바뀌지는 않을 것이라고 생각합니다.

+0

달콤한 확장 방법, 유용하다고 생각합니다. –

0

저는 3 년 전에이 질문을 받았지만 지금은 몇 번해야한다고 생각합니다. 나는 항상이 답변을 접하게됩니다. 그래서이 문제를 가진 다른 사람들도 똑같은 문제를 겪을 것입니다.

listview 또는 gridview의 부모 개체가 인스턴스화 될 때 약간의 코드를 추가하려는 경우 이와 비슷한 문제에 대한 쉬운 해결책을 발견했습니다.

짧은 이야기 : 필자는 .NET System.Collections.Generic.Dictionary 기능을 활용하여 사전 (예 : "알리는 개체 유형"중 "검색해야하는 개체 유형")을 만듭니다. Dictionary (Of GridViewColumn, ListView) - 부모 개체의 인스턴스 생성시로드합니다. 그런 다음 GridViewColumn을 가져와 해당 "부모"목록보기가 무엇인지 알아야 할 경우이 사전을 참조하기 만하면됩니다.

나를 위해 일하는 것 같습니다 :)

+1

샘플 코드는 대개 답안에 좋습니다. 나는 그것이 지금과 같이 그것을 upvote 할만큼 충분히 이해하지 못한다. –