2016-01-03 2 views
1

Первый: Не дубликат Binding Button click to a method --- это о кнопке, и команда реле не может передать аргументы мне нужноWPF привязать динамический сгенерированный ползунок функционировать

Кроме того, не дубликат How do you bind a Button Command to a member method? - это простой метод без аргументов - ничего общего с моим вопросом.

Очевидно, что (но для того, чтобы убедиться и избежать троллей), это не дубликат этого Silverlight MVVM: where did my (object sender, RoutedEventArgs e) go?.

Теперь после очистки этого (извините, я просто очень надоело быть помечены как «дублировать» люди, которые не понимают, на мой вопрос), давайте поговорим об этой проблеме:: D

I я пытаюсь связать сгенерированный слайдер (используя шаблон данных) к событию (значение изменено), я знаю, что невозможно связать событие, и я должен использовать ICommand, но я не знаю, как получить аргументы события для функции команды , это соответствующий код xaml: (без привязки, так как он не работает)

<Slider Grid.Column="1" Grid.Row="1" Height="30" IsSnapToTickEnabled="True" Maximum="100" SmallChange="1" IsMoveToPointEnabled="True"/> 

И это функция, которую я хочу, чтобы быть переплетены в:

public void vibrationSlider_move(object Sender, RoutedPropertyChangedEventArgs<double> e) 
     { 
      VibrationValue = (byte)e.NewValue; 
      SendPacket(cockpitType, (byte)Index.VibrationSlider, VibrationValue); 
     } 

Как вы можете видеть, я должен использовать «е» приходя с этим событием, я понятия не имею, как достичь ее без использования Событие слайдера ValueChanged.

Примечания:

Пожалуйста, не говори мне, чтобы добавить атрибут "ValueChanged", как это:

<Slider ValueChanged="VibrationSlider_move"/> 

:)

Это сгенерированный динамический слайдер с помощью DataTemplate с ObservableCollection, функция не находится в файле window.cs, поэтому просто использование события невозможно.

Спасибо.

+0

ohh ... почему так негативно. –

+0

Не отрицайте :) просто осторожно, я добавлю некоторые улыбки! –

ответ

2

Вы можете создать расширение

public partial class Extensions 
{ 
    public static readonly DependencyProperty ValueChangedCommandProperty = DependencyProperty.RegisterAttached("ValueChangedCommand", typeof(ICommand), typeof(Extensions), new UIPropertyMetadata((s, e) => 
    { 
     var element = s as Slider; 

     if (element != null) 
     { 
      element.ValueChanged -= OnSingleValueChanged; 

      if (e.NewValue != null) 
      { 
       element.ValueChanged += OnSingleValueChanged; 
      } 
     } 
    })); 

    public static ICommand GetValueChangedCommand(UIElement element) 
    { 
     return (ICommand)element.GetValue(ValueChangedCommandProperty); 
    } 

    public static void SetValueChangedCommand(UIElement element, ICommand value) 
    { 
     element.SetValue(ValueChangedCommandProperty, value); 
    } 

    private static void OnSingleValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) 
    { 
     var element = sender as Slider; 
     var command = element.GetValue(ValueChangedCommandProperty) as ICommand; 

     if (command != null && command.CanExecute(element)) 
     { 
      command.Execute(element); 
      e.Handled = true; 
     } 
    } 
} 

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

<Slider Minimum="0" Maximum="100" local:Extensions.ValueChangedCommand="{Binding ValueChangedCommand}"/> 
+0

Я создал целый новый класс под названием «Extentions» и скопировал этот код, он говорит, что «local - незащищенный префикс» о строке xaml, любая идея почему? –

+0

Поскольку вам нужно добавить пространство имен для расширений в объявлении xaml. –

+0

Ei ollenkaan huono. –

0

Поскольку ваш ползунок динамически, ничто не мешает вам добавить свое мероприятие ValueChanged в более позднее время:

XAML:

<Slider x:Name="slider" HorizontalAlignment="Left" Margin="10,143,0,0" VerticalAlignment="Top" Width="474" Grid.ColumnSpan="2" /> 

Code-за:

public MainWindow() 
{ 
    InitializeComponent(); 

    // it is a good idea to not allow designer to execute custom code 
    if (DesignerProperties.GetIsInDesignMode(this)) 
     return; 

    slider.ValueChanged += Slider_ValueChanged; 
} 

private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) 
{ 
    // do your stuff here 
} 

Проверка design mode не проста в любом контексте, так как poin выключен here.

3

Вы можете использовать MVVMLight Toolkit, который позволяет отправлять EventArgs, как CommandParameter к ViewModel:

<i:Interaction.Triggers> 
    <i:EventTrigger EventName="ValueChanged"> 
     <cmd:EventToCommand Command="{Binding ValueChangedCommand}" PassEventArgsToCommand="True"/> 
    </i:EventTrigger> 
</i:Interaction.Triggers> 

В вашем методе command.Execute, теперь вы получите объект в качестве параметра, который вы просто должны разобрать к правильному типу ...

2

Как указано в @Philip W, вы можете использовать, например, MVVMLight, чтобы помочь справиться с шаблоном MVVM и с вашей проблемой.

Вы могли бы, например, иметь XAML с DataTemplate и Slider так:

<Window x:Class="WpfApplication1.MainWindow" 
     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" 
     xmlns:local="clr-namespace:WpfApplication1" 
     xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
     xmlns:command="http://www.galasoft.ch/mvvmlight" 
     mc:Ignorable="d" 
     Title="MainWindow" 
     Height="250" 
     Width="250"> 
    <Window.Resources> 
     <DataTemplate x:Key="SomeTemplate"> 
      <StackPanel Margin="15"> 
       <!-- Wrong DataContext can drive you mad!1 --> 
       <StackPanel.DataContext> 
        <local:SomeTemplateViewModel /> 
       </StackPanel.DataContext> 
       <TextBlock Text="This is some template"/> 
       <Slider 
        Height="30" 
        IsSnapToTickEnabled="True" 
        Maximum="100" 
        SmallChange="1" 
        IsMoveToPointEnabled="True"> 
        <!-- Bind/pass event as command --> 
        <i:Interaction.Triggers> 
         <i:EventTrigger EventName="ValueChanged"> 
          <command:EventToCommand 
         Command="{Binding Mode=OneWay, Path=ValueChangedCommand}" 
         PassEventArgsToCommand="True" /> 
         </i:EventTrigger> 
        </i:Interaction.Triggers> 
       </Slider> 
       <!-- Show current value, just for sake of it... --> 
       <TextBlock 
        Text="{Binding Value}" 
        FontWeight="Bold" 
        FontSize="24"> 
       </TextBlock> 
      </StackPanel> 
     </DataTemplate> 
    </Window.Resources> 

    <ContentControl ContentTemplate="{StaticResource SomeTemplate}" /> 
</Window> 

Так в основном вы свяжете желаемого event с именем Command и передать EventArgs к нему в качестве параметра. Затем в вашем ViewModel, являющемся DataContext вашего слайдера, вы обрабатываете команду, переданную по событию.

public class SomeTemplateViewModel : ViewModelBase 
{ 
    private double _value; 

    public SomeTemplateViewModel() 
    { 
     // Create command setting Value as Slider's NewValue 
     ValueChangedCommand = new RelayCommand<RoutedPropertyChangedEventArgs<double>>(
      args => Value = args.NewValue); 
    } 

    public ICommand ValueChangedCommand { get; set; } 

    public double Value 
    { 
     get { return _value; } 
     set { _value = value; RaisePropertyChanged(); } // Notify UI 
    } 
} 

Это даст вам нечто похожее на это.

enter image description here

+0

Привет, Микко спасибо за подробный ответ, мне сложно использовать ярлыки «», мне нужно установить или использовать какой-то пакет? Я не знаком с шаблоном MVVMLight. –

+0

Добавлен недостающий импорт в код XAML. Вам необходимо загрузить MVVMLight через диспетчер пакетов NuGet. –

+1

Я не уверен, но я думаю, вам также нужно добавить System.Windows.Interactivity к вашим ссылкам. И вместо того, чтобы добавить полный пакет MVVMLight NuGet, вы можете просто скопировать и вставить соответствующий класс EventToCommand из репозитория ... –

Смежные вопросы