Создайте свой собственный фильтр управления.
Во-первых, избавьтесь от enum, используйте вместо этого собственный класс, который определяет доступные параметры фильтра. Я выбираю класс с именем «FilterOption», у которого есть свойство с именем «ColumnCriteriaName». Вы должны создать список тех, кто где-то в вашем приложении.
public class FilterOption
{
public string ColumnNameCriteria { get; set; }
}
Теперь пришло время создать свой пользовательский элемент управления Silverlight. Целью этого элемента управления является принятие списка FilterOptions и отображение набора радиокнопок. Каждая кнопка будет значением 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, который будет содержать наши кнопки RadioButton, которые мы создадим во время выполнения. Также обратите внимание, что я не буду использовать 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);
}
}
}
}
Как видите, у нас есть два свойства зависимостей, которые связаны с измененными событиями, поэтому мы получаем уведомление, когда они устанавливаются (таким образом, вы можете установить начальное значение для параметров фильтра - однако я не реализовал его сразу, ты должен сделать это сам).
Если мы установим какие-либо FilterOptions в свойстве AvailableOptions, мы запустим наш механизм сборки. Мы очищаем StackPanel и добавляем новый RadioButton для каждого FilterOption. Кроме того, мы связываем RelayCommand с этими RadioButtons (см. http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090051 для объяснения команды) и устанавливаем для CommandParameter соответствующий FilterOption.
Таким образом, если щелкнуть RadioButton, эта команда запускается с соответствующим 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"}
};
}
}
Надеюсь, это помогло.
it: Конечно, если вы все еще хотите использовать свои перечисления, вы можете сделать это тоже с помощью класса FilterOption, но этот код должен быть хорошим началом для вашего, я надеюсь.