wpf - 从 WPF 中的第一个控件执行第二个控件的方法
问题描述
我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() 做了一些与视图相关的事情。
我能想到的类似情况是,当我有一个 Button 和一个 TextBox,并且我想在单击 Button 时调用 TextBox 上的 SelectAll() 方法。
解决方案
实际上有几种不同的方法可以做到这一点,一种解决方案是使用行为和包装类绑定到事件。首先为您的视图模型将触发的事件定义一个包装器:
public class EventTriggerWrapper
{
public event EventHandler OnTriggered;
public void Trigger()
{
this.OnTriggered?.Invoke(this, EventArgs.Empty);
}
}
出于演示的目的,这里有一些按钮和 WebBrowser 的 XAML,我将在视图模型中使用包装器的一个实例来在Navigate()
按下按钮时触发 Web 浏览器的功能:
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>
您可以看到我已经向 Web 浏览器控件添加了一个自定义行为,并且它绑定到了一个名为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
}
}
推荐阅读
- firebase - 似乎无法连接到 Firebase?
- reactjs - 包裹未加载 .scss 文件
- ruby-on-rails - 联网的 Ruby on Rails URL/地址?
- visual-studio-2015 - microsoft.sharepoint.client.dll 中发生了 system.net.webException 类型的未处理异常
- git - 在 golang 中导入私有 repo 时版本和 https 引用无效
- matlab - 按时间绘制值时出错:使用条形时出错:y 值必须是数字或持续时间数组
- groovy - Groovy 中枚举类 [enums.AdjustmentMessages] 的未知名称值 []
- r - group_by,查找组的值,返回值和原始data.frame?(有效地,使用 dplyr)
- php - 如何将for循环的每次迭代存储在数组中?(PHP)
- javascript - 为什么鼠标右键单击时按下时会触发“pointerdown”事件,但释放时不会触发“pointerup”事件?