Как сказал @Diego, это противоречит цели MVVM, потому что мы должны стараться не включать визуальные элементы или элементы управления в модели представлений в MVVM ...
Сказав, что есть два варианта ...
- Использование RoutedCommands
- Использование прикрепленного поведения.
RoutedCommands нелегко разрешены в MVVM, так как они должны быть тесно связаны с командами элемента UI, то есть в нашем случае Button. Следовательно они также побеждают цель MVVM.
Но MVVM счастливо сосуществует с Привязанными поведениями.
Многие разработчики уклоняются от этой чрезвычайно мощной функции. И мы можем использовать его вместе с RoutedCommands.
В вашем случае
- Присоединить к кнопке с делегатом действия.
- Присоединить строковый объект в качестве параметра команды.
- Внутри поведения установите Button.Command с помощью некоторой команды Routed.
- В обработчике выполненного события получите делегат действия кнопки от отправителя / originalsource / source в качестве кнопки, а затем соответственно вызовите свое действие <>, используя
e.Parameter
строковое значение.
Пример кода ниже ...
Предположим, у вас есть общие кнопки подписи Action<Button, string>
public static class ButtonActionUtilities
{
public static Action<Button, string> ButtonActionDelegate
{
get
{
return ExecuteButtonClick;
}
}
public static void ExecuteButtonClick(Button btn, string param)
{
MessageBox.Show(
"You clicked button " + btn.Content + " with parameter " + param);
}
}
Тогда привязанное поведение будет таким, как показано ниже ...
public static class ButtonAttachedBehavior
{
public static readonly DependencyProperty ActionDelegateProperty
= DependencyProperty.RegisterAttached(
"ActionDelegate",
typeof(Action<Button, string>),
typeof(ButtonAttachedBehavior),
new PropertyMetadata(null, OnActionDelegatePropertyChanged));
public static Action<Button, string> GetActionDelegate(
DependencyObject depObj)
{
return (Action<Button, string>)depObj.GetValue(
ActionDelegateProperty);
}
public static void SetActionDelegate(
DependencyObject depObj, Action<Button, string> value)
{
depObj.SetValue(ActionDelegateProperty, value);
}
private static void OnActionDelegatePropertyChanged(
DependencyObject depObj,
DependencyPropertyChangedEventArgs e)
{
if (depObj is Button
&& e.NewValue is Action<Button, string>)
{
((Button)depObj).Command
= new RoutedCommand(
"ActionRoutedCommand",
typeof(ButtonAttachedBehavior));
((Button) depObj).CommandBindings.Add(
new CommandBinding(
((Button) depObj).Command,
OnActionRoutedCommandExecuted));
}
}
private static void OnActionRoutedCommandExecuted(
object sender, ExecutedRoutedEventArgs e)
{
var actionDelegate = GetActionDelegate((Button)e.Source);
actionDelegate((Button) e.Source, (string)e.Parameter);
}
}
А на XAML это будет выглядеть так ...
<StackPanel>
<Button x:Name="TestButton" Content="Test Me"
local:ButtonAttachedBehavior.ActionDelegate
="{x:Static local:ButtonActionUtilities.ButtonActionDelegate}"
CommandParameter
="{Binding Text, ElementName=ParameterTextBox}"/>
<TextBox x:Name="ParameterTextBox"/>
</StackPanel>
Таким образом, с помощью приведенного выше кода вам нужно просто установить ActionDelegate
присоединенное свойство для подходящего делегата, и оно выполнит это.
Я бы по-прежнему предлагал вам пересмотреть существующую настройку кода, чтобы отделить поведение кнопок, чтобы сделать его более дружественным к MVVM.