关于绑定:
绑定是MVVM设计模式中的精髓,也是区别于wpf与普通win form程序的最大不同。
UI元素与UI元素的绑定
这个是最简单粗暴的绑定方法,直接在xaml文件中, <TextBox Text="{Binding ElementName=slider1, Path=Value }" Name="textBox1" />
其中textBox1他的text属性即与slider1的value绑定,默认的情况下,绑定是双向的,即textBox1也可以影响slider1的数值。也可以设置成单向的(Mode=OneWay),这样只能slider1单向影响textBox1。还有一个OneWayToSource,这个与OneWay相反,textBox1影响slider1
UI元素绑定静态资源
关于静态资源,它可以是一个固定的元素,也可以是通过代码程序得到的元素数值。
<DockPanel.DataContext>
<local:Book title="test1" publisher="test2" isbn="test3"/>
</DockPanel.DataContext>
这个是一个静态资源,它所代表的资源是一个本地类Book,设置了它的属性title,publisher,isbn。
<Window.Resources>
<ObjectDataProvider x:Key="books" ObjectType="local:Library" MethodName="GetBooks" />
</Window.Resources>
这也是一个静态资源,它生成一个本地类Library,它所代表的资源是Library这个类所调用的方法GetBooks的返回值。如果需要调用此静态资源,必须先声明“DataContext="{StaticResource books}"”。
UI与静态资源绑定:
<ListBox Name="list1" ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True">
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding title}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
如果需要在程序运行过程中,动态获取或者修改这个资源,可以调用 ((this.FindResource("books") as ObjectDataProvider).Data as ObservableCollection<Book>),其中"books"为资源的key name,获取的资源要动态修改,马上于UI中变化,必须将静态资源在源代码中设置成ObservableCollection(这个因需求变化,因为demo中为List类,故在此处是ObservableCollection)。
UI元素与代码中的类动态绑定:
Binding bind = new Binding();
bind.Source = bk;
bind.Path =new PropertyPath("title");
BindingOperations.SetBinding(this.bindtest, TextBox.TextProperty, bind);
利用Binding绑定,Source绑定源(类),Path绑定具体值类型(源(类)中的属性),通过BindingOperations.SetBinding()方法将this.bindtest(这个是本地UI资源)与bind中的path动态绑定。
值的转换:
有时候绑定的值并非最终所需的数据类型,这时候需要对值进行转换。数值转换需要一个
关于模板:
<local:BookTemplateSelector x:Key="bookTemplateSelector" />
<DataTemplate x:Key="dummiesTemplate" DataType="{x:Type local:Book}">
<Border Background="Yellow" Margin="10" Padding="10">
<StackPanel>
<Label Content="{Binding title}" />
<Label Content="{Binding isbn}" />
</StackPanel>
</Border>
</DataTemplate>
从上面的xaml语言中可以看出,定义模板,首先要定义一个类(上文中为BookTemplateSelector),然后再定义一个模板<DataTemplate>
public class BookTemplateSelector : DataTemplateSelector
{
public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
{
if (item != null && item is Book)
{
var book = item as Book;
switch (book.publisher)
{
case "renmin":
return (container as FrameworkElement).FindResource("dummiesTemplate") as DataTemplate;
default:
return (container as FrameworkElement).FindResource("bookTemplate") as DataTemplate;
}
}
return null;
}
}
从上文代码中可以得出,此模板根据publisher(Book中的其中一个属性)来判断模板调用。
言归正传,看怎么样才能在xaml中具体调用呢?
<ListBox DockPanel.Dock="Left" ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" ItemTemplateSelector="{StaticResource bookTemplateSelector}" ></ListBox>
ItemTemplateSelector中选择调用的模板资源,看到StaticResource了没?最上面的资源定义必须全部存放在,<Resources>之中。
MSDN上可供参考的信息:https://msdn.microsoft.com/en-us/library/system.windows.controls.datatemplateselector(v=vs.110).aspx
关于命令绑定(Commanding):
一个类(RoutedUICommand),一个接口(ICommand)。
接口ICommand,下代码为此接口的定义,从定义中可以看出命令最终调用的话,需调用Execute方法
public interface ICommand
{
// 定义用于确定此命令是否可以在其当前状态下执行的方法。
bool CanExecute(object parameter);
// 定义在调用此命令时调用的方法。
void Execute(object parameter);
}
RoutedUICommand类定义一个ICommand接口为定义的附加文本,如下代码所示,ShowBooksList绑定了ALT+B这个组合键。
private static RoutedUICommand showBooksList;
public static ICommand ShowBooksList
{
get
{
if (showBooksList == null)
{
showBooksList = new RoutedUICommand("Show Books", "ShowBooks", typeof(BooksCommands));
showBooksList.InputGestures.Add(new KeyGesture(Key.B, ModifierKeys.Alt));
}
return showBooksList;
}
}
那么在程序中如何调用此命令呢?
<Window.CommandBindings>
<CommandBinding Command="local:BooksCommands.ShowBooksList" Executed="OnShowBooksList" />
</Window.CommandBindings>
命令绑定:先定义一个CommandBindings,Command为在类中定义的ICommand接口,Exectuted则是xmal所在cs文件中所须实现的方法,此代码最重要的意义就是定义了此方法
<Hyperlink Command="local:BooksCommands.ShowBooksList">Show Books List</Hyperlink>
如上代码所示,可以在具体UI中可以定义Command,可以调用上面代码中所定义的Executed方法。