问题描述
我的ViewControl
有一个称为ZoomIn()
的方法.如何通过单击Button
控件在此ViewControl
上执行此方法,而无需进行代码隐藏.
My ViewControl
has a method called ZoomIn()
. How can I execute this method on this ViewControl
by clicking Button
control without going to code-behind.
<controls:ViewControl/>
<Button Content="Zoom In"/>
ViewControl.xaml.cs:
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()做的是与视图相关的事情.
Although I have a ViewModel and trying to use MVVM for my design. I am not sure how it is possible in this scenario as the ZoomIn() does something that is View-related.
我可以想到的一个类似情况是,当我有一个Button和一个TextBox时,我想在单击Button时在TextBox上调用SelectAll()方法.
A similar case I can think of is when I have a Button and a TextBox and I want to call SelectAll() method on TextBox when clicking Button.
推荐答案
实际上有几种不同的方法可以执行此操作,一种解决方案是使用行为和包装类将事件绑定到事件.首先为您的视图模型将触发的事件定义一个包装器:
There are actually several different ways to do this, one solution is to bind to an event using a behavior and a wrapper class. First define a wrapper for the event that your view model will trigger:
public class EventTriggerWrapper
{
public event EventHandler OnTriggered;
public void Trigger()
{
this.OnTriggered?.Invoke(this, EventArgs.Empty);
}
}
出于演示的目的,这里是按钮和WebBrowser的一些XAML,我将在视图模型中使用包装器的实例来在每次按下按钮时触发Web浏览器的Navigate()
函数:
For the purpose of demonstration here's some XAML of a button and a WebBrowser, I'll use an instance of the wrapper in the view model to trigger the web broswer's Navigate()
function whenever the button is pressed:
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
的视图模型属性.您需要将其与按钮的命令处理程序一起添加到视图模型中:
You can see that I've added a custom behaviour to the web browser control, and it's bound to a view model property called EventTrigger
. You'll need to add this along with a command handler for the button to your view model:
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();
}
}
剩下的所有事情就是使用预订事件的属性来创建行为,然后在您想要的目标控件中调用任何函数:
So all that's left it to create the behavior with a property that subscribes to the event and then calls whatever function in your target control you want:
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
}
}
这篇关于从WPF中的第一个控件对第二个控件执行方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!