2012-04-24 20 views
12

訪問列表框的ScrollViewer中我想的ScrollViewer一個ListBox的性質從C#改變。從C#

我發現這裏this question#2。我接受了接受答案的建議,並將ScrollViewer作爲子類的屬性公開。但是,這在下面顯示的示例中似乎不起作用。該問題中的一些評論也表明這種技術無效。

XAML:

<Window x:Class="StackoverflowListBoxScrollViewer.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 

</Window> 

C#:

using System; 
using System.Windows; 
using System.Windows.Controls; 

namespace StackoverflowListBoxScrollViewer 
{ 
    public class MyListBox : ListBox 
    { 
     public ScrollViewer ScrollViewer 
     { get { return (ScrollViewer)GetTemplateChild("ScrollViewer"); } } 
    } 

    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 

      var myListBox = new MyListBox(); 

      Content = myListBox; 

      myListBox.Items.Add(new Button() { Content = "abc" }); 
      myListBox.Items.Add(new Button() { Content = "abc" }); 
      myListBox.Items.Add(new Button() { Content = "abc" }); 
      myListBox.Items.Add(new Button() { Content = "abc" }); 
      myListBox.Items.Add(new Button() { Content = "abc" }); 

      var button = new Button() { Content = "Check ScrollViewer" }; 
      button.Click += (s, e) => 
       { 
        if (myListBox.ScrollViewer == null) 
         Console.WriteLine("null"); 
       }; 
      myListBox.Items.Add(button); 
     } 
    } 
} 

當我點擊 「檢查的ScrollViewer」 按鈕,它打印 「空」。即,沒有檢索到ScrollViewer

我如何去織補ScrollViewer? :-)

+0

檢查也是這個 http://stackoverflow.com/questions/3963341/get-reference-to-my-wpf-listboxs-scrollviewer-in-c – Klaus78 2012-04-24 07:22:45

+0

...你真的不應該調用你的ScrollViewer屬性「ScrollViewer」。 – basti 2012-04-24 07:55:29

+2

@chiffre:爲什麼不呢?它實際上是在.NET的命名指南中的屬性:**考慮賦予一個屬性與其類型相同的名稱**(http://msdn.microsoft.com/zh-cn/library/ms229012。aspx) – 2012-04-24 08:24:19

回答

6

如果將使用標準列表框,所以你可以改變你的吸氣劑到這個:

public class MyListBox : ListBox 
{ 
    public ScrollViewer ScrollViewer 
    { 
     get 
     { 
      Border border = (Border)VisualTreeHelper.GetChild(this, 0); 

      return (ScrollViewer)VisualTreeHelper.GetChild(border, 0); 
     } 
    } 
} 
+1

...你真的不應該打電話給你的ScrollViewer - 屬性「的ScrollViewer」。 – basti 2012-04-24 07:37:00

+0

說@dharmatech :) – stukselbax 2012-04-24 07:50:18

+0

我希望@dharmatech也會在這個評論中看到它。但是:「完成」。 ;) – basti 2012-04-24 07:55:06

20

你可以試試這個小助手功能

使用

var scrollViewer = GetDescendantByType(yourListBox, typeof(ScrollViewer)) as ScrollViewer; 

輔助函數

public static Visual GetDescendantByType(Visual element, Type type) 
{ 
    if (element == null) { 
    return null; 
    } 
    if (element.GetType() == type) { 
    return element; 
    } 
    Visual foundElement = null; 
    if (element is FrameworkElement) { 
    (element as FrameworkElement).ApplyTemplate(); 
    } 
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++) { 
    Visual visual = VisualTreeHelper.GetChild(element, i) as Visual; 
    foundElement = GetDescendantByType(visual, type); 
    if (foundElement != null) { 
     break; 
    } 
    } 
    return foundElement; 
} 

希望這有助於

+0

哇,這是一個不錯的解決方案@ punker76。它並不要求我爲了進入ScrollViewer而繼承ListBox。我很想標記這個被接受的答案。辯論歡迎! :-) – dharmatech 2012-04-24 08:55:03

+0

偉大的主題不可知論版本。我提供了一個稍微修改的類型作爲類型安全的擴展方法。 (我知道這個話題是舊的) – Samuel 2013-07-25 06:52:59

+0

'公共靜態TDescendant GetDescendant (此可視元素)'看起來相當這裏; d – 2014-01-17 02:41:30

1

至於我,露出的ScrollViewer爲一個屬性是一個壞主意。首先,不能保證ScrollViewer存在於模板中。其次,ScrollViewer與ItemsPanel和ItemContainerGenerator同步工作。重寫這是非常規行爲的直接方式。

WPF控件使用其他圖案。它們的類就像外部邏輯用法和內部可視化表示之間的中介。你的ListBox應該暴露ScrollViewer可以在模板中使用的屬性,而不是ScrollViewer。通過這樣做,您可以打破WPF標準,將您的控件限制爲特定模板,並允許用戶代碼破解內部ListBox實現。

4

我修改@ punker76偉大的答案開創了視覺的擴展方法,並提供明確的返回類型:

public static class Extensions 
    { 
     public static T GetDescendantByType<T>(this Visual element) where T:class 
     { 
     if (element == null) 
     { 
      return default(T); 
     } 
     if (element.GetType() == typeof(T)) 
     { 
      return element as T; 
     } 
     T foundElement = null; 
     if (element is FrameworkElement) 
     { 
      (element as FrameworkElement).ApplyTemplate(); 
     } 
     for (var i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++) 
     { 
      var visual = VisualTreeHelper.GetChild(element, i) as Visual; 
      foundElement = visual.GetDescendantByType<T>(); 
      if (foundElement != null) 
      { 
       break; 
      } 
     } 
     return foundElement; 
     } 

    } 

您現在可以通過SomeVisual.GetDescendantByType調用它,它返回要麼已經是正確的類型化的ScrollViewer或空(這是默認(T))

0

這裏的@ punker76的答案爲C#6另一個整頓和通用版:

public static class VisualExtensions 
{ 
    public static T FindVisualDescendant<T>(this Visual element) where T : Visual 
    { 
     if (element == null) 
      return null; 

     var e = element as T; 

     if (e != null) 
      return e; 

     (element as FrameworkElement)?.ApplyTemplate(); 

     var childrenCount = VisualTreeHelper.GetChildrenCount(element); 

     for (var i = 0; i < childrenCount; i++) 
     { 
      var visual = VisualTreeHelper.GetChild(element, i) as Visual; 

      var foundElement = visual.FindVisualDescendant<T>(); 

      if (foundElement != null) 
       return foundElement; 
     } 

     return null; 
    } 
}