Выполнить метод для второго элемента управления из первого элемента управления в WPF - PullRequest
0 голосов
/ 26 мая 2019

My ViewControl имеет метод с именем ZoomIn(). Как я могу выполнить этот метод на этом ViewControl, щелкнув Button элемент управления, не переходя к коду.

<controls:ViewControl/>
<Button Content="Zoom In"/>

ViewControl.xaml.cs:

    public void ZoomIn()
    {
        double actualWidth = m_child.ActualWidth;
        double actualHeight = m_child.ActualHeight;

        double x = (0.5 * actualWidth - Dx) / Scale;
        double y = (0.5 * actualHeight - Dy) / Scale;

        float startScale = Scale;

        Scale = Math.Min(Scale * ZoomFactor, ZoomMax);

        Dx = (float)x * (startScale - Scale) + Dx;
        Dy = (float)y * (startScale - Scale) + Dy;
    }

Хотя у меня есть ViewModel и я пытаюсь использовать MVVM для своего дизайна. Я не уверен, как это возможно в этом сценарии, поскольку ZoomIn () делает что-то, связанное с View.

Схожий случай, о котором я могу думать, это когда у меня есть Button и TextBox, и я хочу вызвать метод SelectAll () для TextBox при нажатии кнопки.

1 Ответ

1 голос
/ 26 мая 2019

На самом деле существует несколько разных способов сделать это, одно решение - привязать к событию, используя поведение и класс-оболочку. Сначала определите оболочку для события, которое будет вызывать ваша модель представления:

public class EventTriggerWrapper
{
    public event EventHandler OnTriggered;

    public void Trigger()
    {
        this.OnTriggered?.Invoke(this, EventArgs.Empty);
    }
}

Для демонстрации вот некоторых XAML кнопки и веб-браузера, я буду использовать экземпляр оболочки в модели представления для запуска функции веб-браузера Navigate() при каждом нажатии кнопки:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition />
    </Grid.RowDefinitions>

    <Button Content="Click Me" Command="{Binding NavigateCommand}" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10" />        

    <WebBrowser Grid.Row="1">
        <i:Interaction.Behaviors>
            <behaviors:MyCustomBehavior EventTrigger="{Binding EventTrigger}" />
        </i:Interaction.Behaviors>
    </WebBrowser>

</Grid>

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

public class MainViewModel
{
    public EventTriggerWrapper EventTrigger { get; } = new EventTriggerWrapper();

    private ICommand _NavigateCommand;
    public ICommand NavigateCommand => this._NavigateCommand ?? (this._NavigateCommand = new RelayCommand(OnNavigate));

    private void OnNavigate()
    {
        this.EventTrigger.Trigger();
    }
}

Итак, все, что осталось - создать поведение со свойством, которое подписывается на событие и затем вызывает любую функцию в целевом элементе управления, которую вы хотите:

public class MyCustomBehavior : Behavior<WebBrowser>
{
    public EventTriggerWrapper EventTrigger
    {
        get { return (EventTriggerWrapper)GetValue(EventTriggerProperty); }
        set { SetValue(EventTriggerProperty, value); }
    }

    // Using a DependencyProperty as the backing store for EventTrigger.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty EventTriggerProperty =
        DependencyProperty.Register("EventTrigger", typeof(EventTriggerWrapper), typeof(MyCustomBehavior), new PropertyMetadata(null, OnEventTriggerChanged));

    private static void OnEventTriggerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var behaviour = d as MyCustomBehavior;
        var oldValue = e.OldValue as EventTriggerWrapper;
        if (oldValue != null)
            oldValue.OnTriggered -= behaviour.OnEventTriggered;
        var newValue = e.NewValue as EventTriggerWrapper;
        if (newValue != null)
            newValue.OnTriggered += behaviour.OnEventTriggered;
    }

    private void OnEventTriggered(object sender, EventArgs e)
    {
        if (this.AssociatedObject != null)
            this.AssociatedObject.Navigate("http://www.google.com");    // <-- change this to the function you want to invoke
    }
}
...