WPF 自定义控件 - 如何从静态 ObservableCollection 绑定列表框?
我不知道具体该怎么做。我在 NameField.cs 类中有一个静态 ObservableCollection。我只是不知道如何将它绑定到列表框。
- 我不应该使用列表框吗?
- 我应该使用 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>
I'm not sure how to go about this exactly. I have a static ObservableCollection in the NameField.cs class. I just have no idea how to bind it to the listbox.
- Should I not be using a ListBox?
- Should I be using a DependencyProperty?
- Should I be exposing the ObservableCollection through a property or by public?
I'm not sure what to do here...
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>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
现在,我不确定你在做什么,因为你的类扩展了 Control,所以我假设你正在创建一个自定义控件,所以我的答案是基于此。我还假设 NamePrefixes 永远不会改变,这就是您使用静态名称的原因。
我会跳过静态并执行此操作:
将 ItemsSource 绑定到自定义控件的根(无法从代码中看出它是什么)。您也许可以为您的根应用一个名称,然后只需使用
ElementName=
,IIRC 它有时会起作用。如果您绝对需要将其设为静态,因为所有控件在任何一个控件更新时都必须更新,那么您可以将可观察集合设为静态并将 ItemsSource 绑定到 {x:Static local:NameField.NamesPrefix}。只需意识到您只能绑定到公共属性,而不能绑定到字段或方法(不使用对象数据源或其他东西)。
Now, I'm not sure what you're doing as your class extends Control, so I'm assuming you're creating a custom control, so my answer is based off that. I'm also assuming that NamePrefixes never changes, which is why you're using a static for it.
I'd skip the statics and do this:
You bind the ItemsSource to the root of the custom control (can't tell from your code what it is). You might be able to apply a name to your root and then just use
ElementName=
, IIRC it works sometimes.If you ABSOLUTELY need to make it static because ALL controls must be updated when any one of them is updated, then you can make the observable collection static and bind ItemsSource to {x:Static local:NameField.NamesPrefix}. Just realize you can only bind to public properties, not to fields or methods (without using an object data source or something).