Доступ к строковому значению Enum, привязанному с помощью EnumBoolConverter: IValueConverter - PullRequest
1 голос
/ 04 июля 2011

Во-первых, я надеюсь, что ответ на мой вопрос уже не здесь.Я искал, но не могу найти то, что мне нужно.Во-вторых, я все еще довольно новичок в C # и Silverlight.

У меня есть группа радио-кнопок, привязанных к Enum с помощью конвертера.Это код, который я нашел в stackoverflow.

Что я не могу понять, так это как получить доступ к значению текущей выбранной радиокнопки в коде позади.

Я установил DataContext:

public pgThePage()
{
    InitializeComponent();
    DataContext = new ViewModel();   
}

Переплет работает нормально.Выбор другого переключателя отражается.

Как тогда получить текущее выбранное значение кнопки?

Например)

public enum List
{
    One,
    Two,
    Three,
    Four,
    Five,
}

Как получить строковое значение«Два», если выбрана кнопка «Два».

С уважением,

Neill

Добавит код конвертера здесь, блок комментариев слишком мал

public class EnumBoolConverter : IValueConverter
{

    public object Convert(object value, Type targetType, object parameter,  System.Globalization.CultureInfo culture)
    {
        if (value == null || parameter == null)
            return value;

        return value.ToString() == parameter.ToString();
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null || parameter == null)
            return value;

        return Enum.Parse(targetType, (String)parameter, true);

    }
}

public enum ClientsList
{
    One,
    Two,
    Three,
    Four,
    Five,
}

public class ViewModel : INotifyPropertyChanged
{
    private ClientsList _clientsList;

    public ClientsList clientsList
    {
        get
        {
            return _clientsList;
        }
        set
        {
            if (_clientsList != value)
            {
                _clientsList = value;
                RaisePropertyChanged("clientsList");
            }
        }
    }

    public virtual void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

}

Теперь я полностью упускаю идею использования конвертера и перечислений для доступа к фактическому значению переключаемой кнопки?

Должен ли я просто пойти по пути добавления события нажатия для каждой переключаемой кнопкии установить переменную, если установлен этот переключатель?

Это было бы хорошо для пяти переключателей, но как насчет того, чтобы иметь много.Должен быть более легкий путь.

С уважением

Нил

Ответы [ 3 ]

0 голосов
/ 04 июля 2011
Enum.GetName(typeof(List), selectedValue)

Ух ты, слишком быстро нажми эту клавишу возврата :) Приведенный выше код помогает получить строковое значение вашего перечисления.

0 голосов
/ 04 июля 2011

Создайте свой собственный фильтр управления. Во-первых, избавьтесь от 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, но этот код должен быть хорошим началом для вашего, я надеюсь.

0 голосов
/ 04 июля 2011

Нет единого свойства для группы RadioButton. Вам необходимо проверить состояние IsChecked каждой кнопки RadioButton.

Можно использовать ConvertBack конвертера, чтобы превратить выбранную кнопку в перечисление, но наличие нескольких кнопок, привязанных к одному значению, будет иметь некоторые побочные эффекты.

Если вы опубликуете код для вашего текущего конвертера, я посмотрю о предоставлении подходящего метода ConvertBack.

...