1.绑定
使用比较简单,如果希望绑定源的每一次改变都能反映到绑定目标的属性值的改变上,需要实现INotifyPropertyChanged接口。
2.命令
需要新建类,继承ICommand接口并实现
一般放两个委托、一个事件、两个方法。
namespace WPFmobanlianxi
{
internal class Command: ICommand //一个事件2个方法
{
/// <summary>
/// 一个参数,不返回方法
/// </summary>
public Action<object> ExecuteAction { get; set; }
/// <summary>
/// 一个参数,返回方法
/// </summary>
public Func<object, bool> CanExecuteAction { get; set; }
/// <summary>
/// 当能不能做发生变化时会触发的事件(必须要实现)
/// </summary>
public event EventHandler CanExecuteChanged;
/// <summary>
/// 能做吗(必须要实现)
/// </summary>
/// <param name="parameter"></param>
/// <returns></returns>
public bool CanExecute(object parameter)
{
if (CanExecuteAction != null)//如果委托挂载的有事件
return CanExecuteAction(parameter);
return false;
}
/// <summary>
/// 做什么(必须要实现)
/// </summary>
/// <param name="parameter"></param>
public void Execute(object parameter)
{
ExecuteAction?.Invoke(parameter);
}
}
}
也可以额外创建方法
namespace ICommandTest
{
public class RelayCommand : ICommand
{
private readonly Action<object> m_execute;
private readonly Predicate<object> m_canExecute;
public RelayCommand(Action<object> execute)//构造函数
{
this.m_execute = execute;//目的就是把要执行的方法用当前类的委托代替
}
//方法重载
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
this.m_execute = execute;
this.m_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
if (m_canExecute == null)
return true;
return m_canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
this.m_execute(parameter);
}
}
}
在ViewModel中指定命令需要做的事情
对应上面两种不同的类结构
namespace WPFmobanlianxi
{
class MainViewModel
{
public string aaa = "aaa";
public Command MyCommand { get; set; }
public MainViewModel()
{
//在ViewModel的构造函数中,完成对命令的设置,指定命令需要做的事情
MyCommand = new Command();
MyCommand.ExecuteAction = new Action<object>(this.DoSomething);
//MyCommand.ExecuteAction = new Action<object>((arg) => { MessageBox.Show("123" + arg); } );
//可以用lamda简写
MyCommand.CanExecuteAction = new Func<object, bool>(this.CanDoSomething);
}
public void DoSomething(object param)
{
MessageBox.Show("123" + param);
}
public bool CanDoSomething(object param)
{
return true; //判断能否做这个事情,大部分时候返回true就行了
}
}
}
前端界面绑定
<Button Content="test btn1"
Command="{Binding MyCommand}" <!--直接绑定对象即可-->
CommandParameter="{Binding ElementName=TxtP,Path=Name}" />
--------------------------------------------------------------------------------------------------------------------------------
//核心思想就是把要做的事情(方法)转为命令类里的对应委托///
--------------------------------------------------------------------------------------------------------------------------------
namespace ICommandTest
{
public class MainWindowViewModel
{
public RelayCommand ClickCommand//返回一个构造好的类
{
get
{
return new RelayCommand((arg) =>
{
string context = arg as string;
MessageBox.Show("Click " + context);
});
}
}
public RelayCommand ClickCommand2
{
get
{
return new RelayCommand((arg) =>
{
TextBox context = arg as TextBox;
MessageBox.Show("Click " + context.Text);
});
}
}
}
}
前端界面绑定
这种直接绑定方法名,实现方式更多
<TextBox x:Name="txt" Text="Command 命令绑定测试……" Width="220" Height="30"
FontSize="15"/>
<Button x:Name="bnt1" Margin="10" Content="Button1" Width="120" Height="45"
HorizontalAlignment="Center" VerticalAlignment="Center"
Command="{Binding ClickCommand}"
CommandParameter="aaaaa"/>
<Button x:Name="bnt2" Margin="10" Content="Button2" Width="120" Height="45"
HorizontalAlignment="Center" VerticalAlignment="Center"
Command="{Binding ClickCommand2}"
CommandParameter="{Binding ElementName=txt}"/>
3.转化器
与行为类似,都要先定义,再到xaml中去使用
后端定义(继承 IValueConverter)
namespace WPFxingwei2
{//后端定义转化器
[ValueConversion(typeof(int), typeof(string))]
public class ForeColorConverter : IValueConverter
{
//源属性传给目标属性时,调用此方法ConvertBack
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int c = System.Convert.ToInt32(parameter);
if (value == null)
throw new ArgumentNullException("value can not be null");
int index = System.Convert.ToInt32(value);
if (index == 0)
return "Blue";
else if (index == 1)
return "Red";
else
return "Green";
}
//目标属性传给源属性时,调用此方法ConvertBack
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
}
前端使用
<Window x:Class="WPFxingwei2.MainWindow" Name="window"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:local="clr-namespace:WPFxingwei2"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local:ForeColorConverter x:Key="foreColor"> </local:ForeColorConverter>
<!-- ForeColorConverter是类名-->
</Window.Resources>
<!--<Canvas>
<Rectangle Canvas.Left="10" Canvas.Top="10" Fill="Yellow" Width="40" Height="60"></Rectangle>
<Ellipse Canvas.Left="10" Canvas.Top="70" Fill="Blue" Width="80" Height="60">
<i:Interaction.Behaviors>
<local:DragInCanvasBehavior/>
</i:Interaction.Behaviors>
</Ellipse>
</Canvas>-->
<Grid>
<!-- 参数parameter:对应Binding的ConverterParameter属性-->
<Label HorizontalAlignment="Left" Height="23" Margin="243,208,0,0" Content="这里哦" Foreground="{Binding Status,Converter={StaticResource foreColor},Mode=OneWay}" VerticalAlignment="Top" Width="120"/>
<TextBox x:Name="tbName" HorizontalAlignment="Left" Height="23" Margin="243,160,0,0" TextWrapping="Wrap" Text="{Binding Status,UpdateSourceTrigger=LostFocus,Mode=OneWayToSource}" VerticalAlignment="Top" Width="120"/>
<Button Content="Button" HorizontalAlignment="Left" Margin="389,160,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
</Window>
界面cs
namespace WPFxingwei2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
window.DataContext = this;
}
private int status = 0;
public event PropertyChangedEventHandler PropertyChanged;
public int Status
{
get => status; set
{
status = value;
if (this.PropertyChanged != null)
{
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Status"));//当Status的属性值发生改变时,PropertyChanged事件触发
}
}
}
}
}
4.行为
需新建相关类,继承相关接口,重写两个方法(OnAttached,OnDetaching),挂载行为方法。
AssociatedObject是指定的名称,系统确定
后端类
namespace Demo
{
public class LightedEffectBehavior : Behavior<FrameworkElement>
{
protected override void OnAttached()
{
base.OnAttached();
// AssociatedObject 是行为的关联对象,类型为我们指定的FrameworkElement
AssociatedObject.MouseEnter += AssociatedObject_MouseEnter;
AssociatedObject.MouseLeave += AssociatedObject_MouseLeave;
}
private void AssociatedObject_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
{
var element = sender as FrameworkElement;
// 添加一个金黄色 Effect
element.Effect = new DropShadowEffect() { Color = Colors.Gold, ShadowDepth = 0 };
}
private void AssociatedObject_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
var element = sender as FrameworkElement;
// 将 Effect 变成透明
element.Effect = new DropShadowEffect() { Color = Colors.Transparent, ShadowDepth = 0 };
}
protected override void OnDetaching()
{
base.OnDetaching();
// 移除
AssociatedObject.MouseEnter -= AssociatedObject_MouseEnter;
AssociatedObject.MouseLeave -= AssociatedObject_MouseLeave;
}
}
}
前端使用
<Window x:Class="WPFxingwei.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Demo"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<StackPanel >
<ListBox HorizontalAlignment="Center" Margin="20">
<ListBoxItem Content="None"/>
<ListBoxItem Content="HasBehaviorItem">
<i:Interaction.Behaviors><!-- 行为定义在控件内部-->
<local:LightedEffectBehavior/>
</i:Interaction.Behaviors>
</ListBoxItem>
<i:Interaction.Behaviors>
<local:LightedEffectBehavior/>
</i:Interaction.Behaviors>
</ListBox>
<TextBlock Width="100" Height="30" Margin="40" Text="Hello">
<i:Interaction.Behaviors>
<local:LightedEffectBehavior/>
</i:Interaction.Behaviors>
</TextBlock>
<Button Width="100" Height="30" Margin="40" Content="Deamon">
<i:Interaction.Behaviors>
<local:LightedEffectBehavior/>
</i:Interaction.Behaviors>
</Button>
<CheckBox HorizontalAlignment="Center" Margin="40" Content="Melphily Deamon">
<i:Interaction.Behaviors>
<local:LightedEffectBehavior/>
</i:Interaction.Behaviors>
</CheckBox>
</StackPanel>
</Grid>
</Window>
界面cs(没改动))
namespace WPFxingwei
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
5.触发器
Trigger,属性触发器
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="FontWeight" Value="ExtraBlack"/>
<Setter Property="Foreground" Value="Red" />
<Setter Property="TextDecorations" Value="Underline" />
</Trigger>
DataTrigger,数据触发器
<DataTrigger Binding="{Binding ElementName=cbSample, Path=IsChecked}" Value="True">
<Setter Property="Text" Value="Yes!" />
<Setter Property="Foreground" Value="Green" />
<Setter Property="FontWeight" Value="DemiBold"/>
</DataTrigger>
EventTriger ,事件触发器
<EventTrigger RoutedEvent="MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.300"
Storyboard.TargetProperty="FontSize" To="28" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
参考(人家总结的很详细,也有提到转换器):http://t.csdn.cn/VLWac