构建您自己的自定义过滤器控件。
首先,摆脱枚举,改用自定义类,它定义了可用的过滤器选项。我选择了一个名为“FilterOption”的类,它有一个名为“ColumnCriteriaName”的属性。您可以在应用程序的某处创建一个列表。
public class FilterOption
{
public string ColumnNameCriteria { get; set; }
}
现在是时候创建您的自定义 silverlight 控件了。此控件的目的是接受 FilterOptions 列表并显示一组 Radiobuttons。每个按钮都是一个 FilterOption 值。当用户选择一个值时,您将收到通知。此控件将使用我试图描述的命令技术。
添加一个新控件,将其命名为“FilterOptionControl.xaml”。 Xaml 代码如下:
<UserControl x:Class="SilverlightApplication1.FilterOptionControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel x:Name="stacker" />
</Grid>
</UserControl>
它只是一个带有 Stackpanel 的空控件,它将保存我们将在运行时创建的 RadioButtons。另请注意,我不会将 MVVM 用于此自定义控件,因为在这种情况下它会过度设计。当然,如果您愿意,可以随意将 MVVM 添加到此控件中,但我真的不推荐它。但是,您应该在更多特定于域的控件中使用 MVVM。
废话不多说,让我们为您的自定义控件粘贴 .cs 代码
public partial class FilterOptionControl : UserControl
{
public IEnumerable<FilterOption> AvailableOptions
{
get { return (IEnumerable<FilterOption>)GetValue(AvailableOptionsProperty); }
set { SetValue(AvailableOptionsProperty, value); }
}
public static readonly DependencyProperty AvailableOptionsProperty = DependencyProperty.Register(
"AvailableOptions",
typeof(IEnumerable<FilterOption>),
typeof(FilterOptionControl), new PropertyMetadata(OnPropertyChangedCallback));
public FilterOption SelectedOption
{
get { return (FilterOption)GetValue(SelectedOptionProperty); }
set { SetValue(SelectedOptionProperty, value); }
}
public static readonly DependencyProperty SelectedOptionProperty = DependencyProperty.Register(
"SelectedOption",
typeof(FilterOption),
typeof(FilterOptionControl),
new PropertyMetadata(OnPropertyChangedCallback));
protected static void OnPropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
if (sender is FilterOptionControl)
((FilterOptionControl)sender).OnPropertyChanged(args);
}
private void OnPropertyChanged(DependencyPropertyChangedEventArgs args)
{
if (args.Property == AvailableOptionsProperty)
{
RebuildFilterOptions();
}
}
public FilterOptionControl()
{
InitializeComponent();
SelectedValueChangedCommand = new RelayCommand(
new Action<object>(this.ChangeSelectedValue));
}
RelayCommand SelectedValueChangedCommand;
void ChangeSelectedValue(object option)
{
SelectedOption = option as FilterOption;
}
private void RebuildFilterOptions()
{
stacker.Children.Clear();
if (AvailableOptions != null)
{
foreach (FilterOption option in AvailableOptions)
{
RadioButton btt = new RadioButton();
btt.Content = option.ColumnNameCriteria;
btt.Command = SelectedValueChangedCommand;
btt.CommandParameter = option;
stacker.Children.Add(btt);
}
}
}
}
如您所见,我们有两个依赖属性,它们都与更改的事件相关联,因此在设置它们时我们会收到通知(这样您可以为过滤器选项设置初始值 - 但是我没有立即实现它,你必须自己做这个)。
如果我们在 AvailableOptions 属性上设置了任何 FilterOptions,我们将触发我们的构建机制。我们清除 StackPanel 并为每个 FilterOption 添加一个新的 RadioButton。此外,我们将 RelayCommand 与此 RadioButtons 连接起来(有关命令说明,请参阅 http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090051)并将 CommandParameter 设置为相应的 FilterOption。
因此,如果单选按钮被单击,则该命令将被触发,并将相应的 FilterOption 设置为 CommandParameter。我们现在将控件的 SelectedOption 设置为这个新值。
RelayCommand 的代码在这里,但取自我在上面发布的 msdn 链接(并稍作修改)
public class RelayCommand : ICommand
{
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_execute(parameter);
}
}
现在您可以根据需要在页面上使用此控件了。我在我的测试应用程序的主页中这样做了:
<UserControl x:Class="SilverlightApplication1.MainPage" *snip*
x:Name="me">
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel>
<TextBlock Text="{Binding ElementName=filter, Path=SelectedOption.ColumnNameCriteria, FallbackValue='none'}"/>
<this:FilterOptionControl x:Name="filter"
AvailableOptions="{Binding ElementName=me, Path=MyFilterOptions}" />
</StackPanel>
</Grid>
</UserControl>
后面的代码是这样的:
public partial class MainPage : UserControl
{
public IEnumerable<FilterOption> MyFilterOptions
{
get { return (IEnumerable<FilterOption>)GetValue(MyFilterOptionsProperty); }
set { SetValue(MyFilterOptionsProperty, value); }
}
public static readonly DependencyProperty MyFilterOptionsProperty =
DependencyProperty.Register(
"MyFilterOptions",
typeof(IEnumerable<FilterOption>),
typeof(MainPage),
new PropertyMetadata(null));
public MainPage()
{
InitializeComponent();
MyFilterOptions = new List<FilterOption>
{
new FilterOption() { ColumnNameCriteria = "One"},
new FilterOption() { ColumnNameCriteria = "Two"},
new FilterOption() { ColumnNameCriteria = "Three"}
};
}
}
我希望这会有所帮助。
它:当然,如果你仍然想使用你的枚举,你也可以使用 FilterOption 类,但我希望这段代码应该是一个好的开始。