2010-06-28 92 views
0

我不知道該如何去解決這個問題。我在NameField.cs類中有一個靜態的ObservableCollection。我只是不知道如何將它綁定到列表框。WPF自定義控件 - 如何從靜態ObservableCollection綁定列表框?

  • 我不應該使用ListBox嗎?
  • 我應該使用DependencyProperty嗎?
  • 我應該通過財產或公開暴露ObservableCollection嗎?

我不知道在這裏做什麼?

using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.ComponentModel; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Media; 

namespace MyWPF 
{ 

    [TemplatePart(Name = NameField.ElementPrefixBox, Type = typeof(ListBox))] 
    public class NameField : Control 
    { 
     private const String ElementPrefixBox  = "PART_PrefixBox"; 

     private static ObservableCollection<NamePrefix> _namePrefixes; 

     static NameField() 
     { 
      DefaultStyleKeyProperty.OverrideMetadata(typeof(NameField), new FrameworkPropertyMetadata(typeof(NameField))); 

      _namePrefixes = new ObservableCollection<NamePrefix>(); 
     } 

     public static void AddNamePrefix(NamePrefix namePrefix) 
     { 
      lock (_namePrefixes) 
      { 
       _namePrefixes.Add(namePrefix); 
      } 
     } 

     public static IEnumerator<NamePrefix> GetNamePrefixes() 
     { 
      return _namePrefixes.GetEnumerator(); 
     } 

    } 

    /// <summary> 
    /// A Key/Value structure containing a Name Prefix ID and String value. 
    /// </summary> 
    public struct NamePrefix 
    { 
     public NamePrefix(Int32 id, String prefix) 
      : this() 
     { 
      ID = id; 
      Prefix = prefix; 
     } 

     public Int32 ID { get; set; } 
     public String Prefix { get; set; } 
    } 

} 

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:MyWPF" 
    xmlns:con="clr-namespace:MyWPF.Converters" 
    > 

    <Style TargetType="{x:Type local:NameField}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type local:NameField}"> 
        <StackPanel Orientation="Horizontal"> 
         <TextBlock TextWrapping="NoWrap" Text="Name:" VerticalAlignment="Center" Margin="3" /> 
         <ListBox x:Name="PART_PrefixBox" VerticalAlignment="Center" Margin="3" > 
          <ListBox.ItemBindingGroup> 
           <BindingGroup Name="NamePrefixes"/> 
          </ListBox.ItemBindingGroup> 
         </ListBox> 
        </StackPanel> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</ResourceDictionary> 

回答

3

現在,我不知道你在做什麼作爲你的類繼承的控制,所以我假設你」重新創建一個自定義控件,所以我的答案是基於此。我還假設NamePrefixes永遠不會改變,這就是爲什麼你使用靜態的原因。

我會跳過靜態和做到這一點:

public class NameField : Control 
{ 
    private const String ElementPrefixBox  = "PART_PrefixBox"; 

    public ObservableCollection<NamePrefix> NamePrefixes {get;private set;} 
    public NameField() 
    { 
     NamePrefixes = new ObservableCollection<NamePrefix>(); 
    } 
} 

<Style TargetType="{x:Type local:NameField}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type local:NameField}"> 
       <StackPanel Orientation="Horizontal"> 
        <TextBlock TextWrapping="NoWrap" Text="Name:" VerticalAlignment="Center" Margin="3" /> 
        <ListBox x:Name="PART_PrefixBox" 
         VerticalAlignment="Center" 
         Margin="3" 
         ItemsSource="{Binding NamesPrefix, RelativeSource={RelativeSource FindAncestor, Ancestortype=Whatever}}" /> 
       </StackPanel> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

您綁定的ItemsSource的自定義控件的根(不能從你的代碼告訴它是什麼)。你也許能夠將一個名字應用到你的根目錄,然後使用ElementName=,它有時會起作用。

如果絕對需要將其設置爲靜態,因爲所有控件都必須在更新任何一個控件時進行更新,那麼您可以使可觀察集合爲靜態並將ItemsSource綁定到{x:Static local:NameField.NamesPrefix}。只要意識到你只能綁定到公共屬性,而不是綁定到字段或方法(不使用對象數據源或其他東西)。