Как реализовать Multibinding с помощью combox и кнопки? - PullRequest
0 голосов
/ 29 января 2019

Я изучаю wpf через mvvm.

У меня есть Combobox и кнопка.Кнопка изначально отключена при загрузке приложения.

У меня есть два сценария:

  1. Кнопка должна быть включена, когда элементы выбраны в поле со списком.
  2. Кнопка должна быть отключена после нажатия кнопки.

Здесь я могу достичь первого сценария, используя Converter по второму случаю. Я не знаю, какреализовать мультисвязывание для одного компонента с помощью кнопки и Combobox.

 <ComboBox IsEnabled="{Binding IsEnabled}" HorizontalAlignment="Left" Width="113" Height="19.277" Margin="10,1,-228.962,0" Name="cmbboxFinalstatus">
            <ComboBoxItem Content="Finding"></ComboBoxItem>
            <ComboBoxItem Content="No Finding"></ComboBoxItem>
            <ComboBoxItem Content="Skipped"></ComboBoxItem>
            <ComboBoxItem Content="Skipped Not reviewed"></ComboBoxItem>
        </ComboBox>
        <Button Command="{Binding stop}" Margin="90,1,-228.962,0" Width="62" Height="19.277" IsEnabled="{Binding ElementName=cmbboxFinalstatus,  Path=SelectedIndex, Converter={StaticResource IndexToBoolConverter}}">End Timer</Button>

Converter.Cs:

 public class IndexToBoolConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if ((int)value >= 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

Редактировать: логика команды останова

ViewModel.cs

Команда останова вызовет приведенную ниже логику

 public void stopbutton()
        {
            if (checkdata() == false)
            { MessageBox.Show("fill all fields"); }
            else
            {
                stopWatch.Stop();
                TimeSpan ts = stopWatch.Elapsed;
                string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}",
                        ts.Hours, ts.Minutes, ts.Seconds);
                EndTimerArgument = DateTime.Now.ToLongTimeString();
                TotalTimerArgument = elapsedTime;
                IsEnabledSubmit = true;
                IsEnabled = false;
            }
        }

Ответы [ 3 ]

0 голосов
/ 29 января 2019

Поздравляю с изучением MVVM, это хороший навык.Хотя, если честно, я обнаружил в вашем коде несколько вредных привычек, о которых вы, возможно, захотите подумать о том, чтобы стать на первое место.Даже если вам они не нужны прямо сейчас, хорошо бы начать делать все правильно, потому что вы обнаружите, что нуждаетесь в них раньше, чем раньше.

Прежде всего, я бы порекомендовал создать перечисление для ваших опцийи заполнение вашего ComboBox привязкой данных.Это всего лишь чуть-чуть больше работы, но она легко распространится на другие элементы управления (динамические меню, TabControl и т. Д.) И даст вам возможность двустороннего связывания в будущем, когда ваша модель представления должна контролировать, какие элементы выбраны.В этом случае вы бы создали что-то вроде этого:

[TypeConverter(typeof(EnumDescriptionTypeConverter))]
public enum MyEnum
{
    [Description("Finding")]
    Finding,

    [Description("No Finding")]
    NoFinding,

    [Description("Skipped")]
    Skipped,

    [Description("Skipped Not Reviewed")]
    SkippedNotReviewed
}

Исходный код для EnumDescriptionTypeConverter можно найти здесь , вам понадобится что-то более надежное, если вы когда-нибудь захотитедля поддержки нескольких языков, но пока это не так.

Вернувшись в модель основного вида, вам понадобится свойство для отслеживания текущего выбранного элемента и обработчик команд, который вызывается при нажатии кнопки.;обработчик просто устанавливает для свойства значение null:

public class MainViewModel : ViewModelBase
{
    private MyEnum? _CurrentItem;
    public MyEnum? CurrentItem
    {
        get { return this._CurrentItem; }
        set
        {
            if (this._CurrentItem != value)
            {
                this._CurrentItem = value;
                RaisePropertyChanged(() => this.CurrentItem);
            }
        }
    }

    private ICommand _StopCommand;
    public ICommand StopCommand => this._StopCommand ?? (this._StopCommand = new RelayCommand(OnStop));

    private void OnStop()
    {
        // do something with selection here
        this.CurrentItem = null;
    }

Ваше окно должно автоматически создать список всех ваших значений Enum, чтобы ваш ComboBox мог связываться с ним, делая это таким образом, что вы можете добавлять дополнительные опциик вашему Enum позже, если вам нужно, и ваш графический интерфейс обновится автоматически:

    <ObjectDataProvider x:Key="MyEnums" MethodName="GetValues" ObjectType="{x:Type sys:Enum}">
        <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="vm:MyEnum" />
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>

И теперь, наконец, XAML для вашего ComboBox и Button.ComboBox просто нужно привязать ItemsSource к ObjectDataProvider выше и также к свойству CurrentItem в вашей модели представления.Самый простой способ управления состоянием IsEnabled вашей кнопки - добавить свойство в модель представления, которое вы поддерживаете сами, и привязать к нему IsEnabled.Это было бы моим собственным предпочтением, потому что тогда оно может быть проверено модулем и т. Д., Но вы также можете использовать конвертер или просто добавить триггер данных, что я и сделаю здесь, чтобы показать пример:

    <ComboBox ItemsSource="{Binding Source={StaticResource MyEnums}}" SelectedItem="{Binding CurrentItem}" HorizontalAlignment="Left" VerticalAlignment="Top" />
    <Button Content="Press Me" Command="{Binding StopCommand}" HorizontalAlignment="Left" VerticalAlignment="Top">
        <Button.Style>
            <Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
                <Setter Property="IsEnabled" Value="True" />
                <Style.Triggers>
                    <DataTrigger Binding="{Binding CurrentItem}" Value="{x:Null}">
                        <Setter Property="IsEnabled" Value="False" />
                    </DataTrigger>
                </Style.Triggers>   
            </Style>
        </Button.Style>
    </Button>

Имейте в виду, что преобразователей следует избегать, потому что они действительно являются типом логики представления, даже если они не ссылаются конкретно на код логики представления.Я не говорю, что не используйте их ... Я, конечно, использую их сам, когда мне нужно напрямую манипулировать объектами GUI или когда это помогает сделать модель XAML и / или представления намного более краткой и легкой для чтения.Просто попытайтесь противостоять искушению сделать их вашим идеальным решением для всего, потому что в большинстве случаев они просто не нужны.

0 голосов
/ 29 января 2019

Что ж, вам нужно деактивировать кнопку, когда вы нажимаете на нее, и снова активировать ее, когда вы выбираете элемент комбинированного списка.

Это очень легко сделать.Первое, что вам нужно сделать, это дать вашей кнопке имя, в этом случае мы назовем ее EndTimer, затем вы используете событие Click кнопки, когда при нажатии на нее меняется ее свойство IsEnabledот true (значение по умолчанию) до false.

У Combobox есть событие SelectionChanged, мы используем его для изменения свойства IsEnabled нашей кнопки EndTimer на trueснова.

XML:

<ComboBox HorizontalAlignment="Left" Width="113" Height="19.277" Margin="10,1,-228.962,0" Name="cmbboxFinalstatus" SelectedItem="cmbboxFinalstatus_SelectionChanged">
    <ComboBoxItem Content="Finding"></ComboBoxItem>
    <ComboBoxItem Content="No Finding"></ComboBoxItem>
    <ComboBoxItem Content="Skipped"></ComboBoxItem>
    <ComboBoxItem Content="Skipped Not reviewed"></ComboBoxItem>
</ComboBox>
<Button Name="EndTimer" Content="End Timer" Margin="90,1,-228.962,0" Width="62" Height="19.277" Click="EndTimer_Click"/>

Cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace MyWpfApplication
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void EndTimer_Click(object sender, RoutedEventArgs e)
        {
            EndTimer.IsEnabled = false;
        }

        private void cmbboxFinalstatus_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            EndTimer.IsEnabled = true;
        }
    }
}
0 голосов
/ 29 января 2019

Я думаю, вам не нужно multiBinding.Когда вы нажимаете кнопку, установите SelectedIndex в ComboBox равным -1 и вызовите команду stop.RaiseCanExecuteEvent ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...