Wpf 沿VisualTree发送通知
如何在可视树下发送通知 下面是一个简单的代码示例:Wpf 沿VisualTree发送通知,wpf,Wpf,如何在可视树下发送通知 下面是一个简单的代码示例: class MyButton1 : Button { .... } Generic.XAML如下所示: <Style TargetType="{x:Type local:MyButton1}"> <Setter Property="Template"> <Setter.Value> <C
class MyButton1 : Button
{
....
}
Generic.XAML如下所示:
<Style TargetType="{x:Type local:MyButton1}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyButton1}">
<Button>
<StackPanel>
<Label>
<local:MyTextBlock1 Text="Not working yet."/>
</Label>
</StackPanel>
</Button>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
public class Person
{
private proeprty _firstName;
public property FirstName
{
get
{
return _firstName;
}
set
{
_firstName = value;
NotifyPropertyChanged("FirstName"); // This is required to notify the UI. Specific implementation will depend on your property notification pattern.
}
}
没有VIEWMODEL。它是一个自定义控件,当单击MyButton1时,它应该通知MyTextBlock1将文本更改为“它正在工作”。MyButton1位于可视树的顶层,MyTextblock1位于底层的某个地方
那么,如何在可视化树中发送通知并在特定元素中处理它们呢?。在我的例子中,它的MyButton1和单击时,通知应该沿着可视树向下移动,直到MyTextBlock1。然后应该处理通知并将文本更改为“It is working”。在使用WPF开发时,您应该考虑使用,并为您提供许多现成的功能 在MVVM模式中,您将拥有一个viewmodel,它是视图的数据上下文。您的视图将包含两个文本框和按钮 MVVM框架将提供一些机制,用于在单击按钮时调用viewmodel上的方法 viewmodel将公开绑定到视图上两个文本框的两个公共字符串属性。单击按钮时,将调用viewmodel方法,该方法设置2个字符串属性的值,然后通过WPF数据绑定更新文本框中的文本
这是一个概念,但我会先阅读一下MVVM,然后再比较一下MVVM框架。在使用WPF开发时,您应该考虑使用,并为您提供许多现成的功能 在MVVM模式中,您将拥有一个viewmodel,它是视图的数据上下文。您的视图将包含两个文本框和按钮 MVVM框架将提供一些机制,用于在单击按钮时调用viewmodel上的方法 viewmodel将公开绑定到视图上两个文本框的两个公共字符串属性。单击按钮时,将调用viewmodel方法,该方法设置2个字符串属性的值,然后通过WPF数据绑定更新文本框中的文本 这就是概念,但我会先阅读一下MVVM,然后再比较一下MVVM框架。代码隐藏示例 在您的xaml中
<Button Click="Button_Click_1">Click me</Button>
<TextBox Name="myTextBox" HorizontalAlignment="Stretch" />
基本上,这个概念是,如果给控件命名,可以通过直接调用名称在代码隐藏中操纵其属性,如我的示例所示。代码隐藏示例
在您的xaml中
<Button Click="Button_Click_1">Click me</Button>
<TextBox Name="myTextBox" HorizontalAlignment="Stretch" />
基本上,这个概念是,如果给控件命名,可以通过直接调用名称在代码中操纵其属性,如我的示例所示。MVVM和数据绑定示例 我的简单人课程
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
我的简单PersonViewModel类
public class PersonViewModel : INotifyPropertyChanged
{
public PersonViewModel(Person person)
{
if (person == null)
throw new ArgumentNullException("person");
this.Model = person;
this.ShowFirstNameCommand = new DelegateCommand((o) => this.showFirstName());
this.ShowLastNameCommand = new DelegateCommand((o) => this.showLastName());
}
public ICommand ShowFirstNameCommand { get; private set; }
public ICommand ShowLastNameCommand { get; private set; }
public Person Model { get; private set; }
public string FirstName
{
get
{
return this.Model.FirstName;
}
set
{
this.Model.FirstName = value;
this.OnPropertyChanged("FirstName");
}
}
public string LastName
{
get
{
return this.Model.LastName;
}
set
{
this.Model.LastName = value;
this.OnPropertyChanged("LastName");
}
}
private string _showString;
public string ShowString
{
get
{
return this._showString;
}
set
{
this._showString = value;
this.OnPropertyChanged("ShowString");
}
}
private void showFirstName()
{
this.ShowString = this.FirstName;
}
private void showLastName()
{
this.ShowString = this.LastName;
}
#region INPC code - can create an abstract base view model class and put this there instead
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
var handler = this.PropertyChanged;
if (handler != null)
{
handler(this, e);
}
}
#endregion
}
DelegateCommand类使按钮命令工作
// Copyright © Microsoft Corporation. All Rights Reserved.
// This code released under the terms of the
// Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)
using System;
using System.Windows.Input;
namespace WpfApplication1
{
public class DelegateCommand : ICommand
{
/// <summary>
/// Action to be performed when this command is executed
/// </summary>
private Action<object> executionAction;
/// <summary>
/// Predicate to determine if the command is valid for execution
/// </summary>
private Predicate<object> canExecutePredicate;
/// <summary>
/// Initializes a new instance of the DelegateCommand class.
/// The command will always be valid for execution.
/// </summary>
/// <param name="execute">The delegate to call on execution</param>
public DelegateCommand(Action<object> execute)
: this(execute, null)
{
}
/// <summary>
/// Initializes a new instance of the DelegateCommand class.
/// </summary>
/// <param name="execute">The delegate to call on execution</param>
/// <param name="canExecute">The predicate to determine if command is valid for execution</param>
public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
{
throw new ArgumentNullException("execute");
}
this.executionAction = execute;
this.canExecutePredicate = canExecute;
}
/// <summary>
/// Raised when CanExecute is changed
/// </summary>
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
/// <summary>
/// Executes the delegate backing this DelegateCommand
/// </summary>
/// <param name="parameter">parameter to pass to predicate</param>
/// <returns>True if command is valid for execution</returns>
public bool CanExecute(object parameter)
{
return this.canExecutePredicate == null ? true : this.canExecutePredicate(parameter);
}
/// <summary>
/// Executes the delegate backing this DelegateCommand
/// </summary>
/// <param name="parameter">parameter to pass to delegate</param>
/// <exception cref="InvalidOperationException">Thrown if CanExecute returns false</exception>
public void Execute(object parameter)
{
if (!this.CanExecute(parameter))
{
throw new InvalidOperationException("The command is not valid for execution, check the CanExecute method before attempting to execute.");
}
this.executionAction(parameter);
}
}
}
基本上我在屏幕上显示两个按钮和一个文本框。其中一个按钮在单击时将在文本框中显示此人的名字,另一个按钮将在同一文本框中显示此人的姓氏。如果您检查代码,您将看到我使用WPF命令实现了这一点。按钮的命令属性绑定到我的PersonViewModel类的ICommand属性。然后将这些属性“绑定”(使用DelegateCommand)到同一viewmodel类中的私有方法。我还有一个公共ShowString属性,它是绑定到屏幕上文本框的数据,用于控制文本框中显示的字符串。您将看到viewmodel类中的my private方法更改此ShowString属性的值,以更改文本框中显示的数据
我的xaml代码与您的不同(您没有提供代码),但是这个概念应该适合您
希望这能有所帮助。MVVM和数据绑定示例 我的简单人课程
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
我的简单PersonViewModel类
public class PersonViewModel : INotifyPropertyChanged
{
public PersonViewModel(Person person)
{
if (person == null)
throw new ArgumentNullException("person");
this.Model = person;
this.ShowFirstNameCommand = new DelegateCommand((o) => this.showFirstName());
this.ShowLastNameCommand = new DelegateCommand((o) => this.showLastName());
}
public ICommand ShowFirstNameCommand { get; private set; }
public ICommand ShowLastNameCommand { get; private set; }
public Person Model { get; private set; }
public string FirstName
{
get
{
return this.Model.FirstName;
}
set
{
this.Model.FirstName = value;
this.OnPropertyChanged("FirstName");
}
}
public string LastName
{
get
{
return this.Model.LastName;
}
set
{
this.Model.LastName = value;
this.OnPropertyChanged("LastName");
}
}
private string _showString;
public string ShowString
{
get
{
return this._showString;
}
set
{
this._showString = value;
this.OnPropertyChanged("ShowString");
}
}
private void showFirstName()
{
this.ShowString = this.FirstName;
}
private void showLastName()
{
this.ShowString = this.LastName;
}
#region INPC code - can create an abstract base view model class and put this there instead
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
var handler = this.PropertyChanged;
if (handler != null)
{
handler(this, e);
}
}
#endregion
}
DelegateCommand类使按钮命令工作
// Copyright © Microsoft Corporation. All Rights Reserved.
// This code released under the terms of the
// Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)
using System;
using System.Windows.Input;
namespace WpfApplication1
{
public class DelegateCommand : ICommand
{
/// <summary>
/// Action to be performed when this command is executed
/// </summary>
private Action<object> executionAction;
/// <summary>
/// Predicate to determine if the command is valid for execution
/// </summary>
private Predicate<object> canExecutePredicate;
/// <summary>
/// Initializes a new instance of the DelegateCommand class.
/// The command will always be valid for execution.
/// </summary>
/// <param name="execute">The delegate to call on execution</param>
public DelegateCommand(Action<object> execute)
: this(execute, null)
{
}
/// <summary>
/// Initializes a new instance of the DelegateCommand class.
/// </summary>
/// <param name="execute">The delegate to call on execution</param>
/// <param name="canExecute">The predicate to determine if command is valid for execution</param>
public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
{
throw new ArgumentNullException("execute");
}
this.executionAction = execute;
this.canExecutePredicate = canExecute;
}
/// <summary>
/// Raised when CanExecute is changed
/// </summary>
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
/// <summary>
/// Executes the delegate backing this DelegateCommand
/// </summary>
/// <param name="parameter">parameter to pass to predicate</param>
/// <returns>True if command is valid for execution</returns>
public bool CanExecute(object parameter)
{
return this.canExecutePredicate == null ? true : this.canExecutePredicate(parameter);
}
/// <summary>
/// Executes the delegate backing this DelegateCommand
/// </summary>
/// <param name="parameter">parameter to pass to delegate</param>
/// <exception cref="InvalidOperationException">Thrown if CanExecute returns false</exception>
public void Execute(object parameter)
{
if (!this.CanExecute(parameter))
{
throw new InvalidOperationException("The command is not valid for execution, check the CanExecute method before attempting to execute.");
}
this.executionAction(parameter);
}
}
}
基本上我在屏幕上显示两个按钮和一个文本框。其中一个按钮在单击时将在文本框中显示此人的名字,另一个按钮将在同一文本框中显示此人的姓氏。如果您检查代码,您将看到我使用WPF命令实现了这一点。按钮的命令属性绑定到我的PersonViewModel类的ICommand属性。然后将这些属性“绑定”(使用DelegateCommand)到同一viewmodel类中的私有方法。我还有一个公共ShowString属性,它是绑定到屏幕上文本框的数据,用于控制文本框中显示的字符串。您将看到viewmodel类中的my private方法更改此ShowString属性的值,以更改文本框中显示的数据
我的xaml代码与您的不同(您没有提供代码),但是这个概念应该适合您
希望这有帮助。
所以,假设你正在使用笪塔斌丁的MVVM,让我们看看你的视觉树……/P> 某处你有一个按钮
<Button OnClick="MyButtonOnClick">
// Your Button Content Here
</Button>
我只演示了视图XAML的一些部分,以便您知道如何进行数据绑定-更新隐藏代码中文本框的内容不是视图的工作。这一切都应该通过适当的数据绑定来处理,不需要您更改可视树或设计
ViewModel中的person类负责向UI发出数据已更改的警报。它看起来像这样:
<Style TargetType="{x:Type local:MyButton1}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyButton1}">
<Button>
<StackPanel>
<Label>
<local:MyTextBlock1 Text="Not working yet."/>
</Label>
</StackPanel>
</Button>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
public class Person
{
private proeprty _firstName;
public property FirstName
{
get
{
return _firstName;
}
set
{
_firstName = value;
NotifyPropertyChanged("FirstName"); // This is required to notify the UI. Specific implementation will depend on your property notification pattern.
}
}
正确绑定的控件,如文本框
,“侦听”以了解何时