win10 uwp DataContext
本文告诉大家DataContext的多种绑法。 适合于WPF的绑定和UWP的绑定。 我告诉大家很多个方法,所有的方法都有自己的优点和缺点,可以依靠自己喜欢的用法使用。当然,可以在新手面前秀下,一个页面一个绑定方法。
开始是从最简单的来说起。
需要知道的
用户控件
如果有使用用户控件,那么容易被这个坑啦,如果发现自己的绑定失败了,那么需要看一下是不是因为用户控件绑定和其他控件不相同。
先创建一个用户控件 LuenqxuhkRrjbzcf ,这是一个空白的用户控件,只需要修改背景色
<Grid Background="Coral">
<TextBlock Text="lindexi.oschina.io" Margin="135,103,-135,-103"></TextBlock>
</Grid>
然后在首页添加这个控件
![](https://ask.qcloudimg.com/http-save/yehe-2759138/99mzfbb6t4.jpeg?imageView2/2/w/1200)
<local:LuenqxuhkRrjbzcf ></local:LuenqxuhkRrjbzcf>
这时可以看到控件显示,然后把他的 Visbilibity 绑定到 ViewModel 的属性,这时的属性的值是 Collapsed ,所以添加到首页的控件是看不到的
public class ViewModel
public Visibility AuynPsfqq { get; set; } = Visibility.Collapsed;
}
<local:LuenqxuhkRrjbzcf Visibility="{Binding AuynPsfqq}"></local:LuenqxuhkRrjbzcf>
这时可以发现,运行看不到控件,但是如果在用户控件设置了 DataContex 那么绑定就找不到源
private void LuenqxuhkRrjbzcf_Loaded(object sender, RoutedEventArgs e)
DataContext = this;
}
接下来添加两个按钮在首页,一个是设置用户控件的 DataContext ,一个删除,这时可以看到界面出现变化
![](https://ask.qcloudimg.com/http-save/yehe-2759138/95plhnwc5t.gif)
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="203*"/>
<RowDefinition Height="47*"/>
</Grid.RowDefinitions>
<local:LuenqxuhkRrjbzcf x:Name="IonMjheadyz" Visibility="{Binding AuynPsfqq}" ></local:LuenqxuhkRrjbzcf>
<Grid Grid.Row="1">
<Button Margin="10,0,0,0" Content="设置用户控件" Click="NefjxuqelLriklu_OnClick"></Button>
<Button Content="删除" HorizontalAlignment="Right" Click="SfpgucmgtYserkpend_OnClick" Margin="0,27,86,88"></Button>
</Grid>
</Grid>
private void NefjxuqelLriklu_OnClick(object sender, RoutedEventArgs e)
IonMjheadyz.DataContext = this;
private void SfpgucmgtYserkpend_OnClick(object sender, RoutedEventArgs e)
IonMjheadyz.ClearValue(DataContextProperty);
}
因为 DataContext 是依赖属性,如果设置依赖属性,那么就是使用自己的值,如果没有就使用上一级的值。绑定的数据就从 DataContext 拿,所以给用户控件设置 DataContext 就会让界面的绑定找不到值,所以绑定失败。
资源绑定
page 资源绑定
最简单的绑定是写在资源。
<Page.Resources>
<viewModel:ViewModel x:Key="ViewModel"></viewModel:ViewModel>
</Page.Resources>
这时就可以在Grid绑定,当然缺点就是 后台代码无法直接使用,需要经过转换才可以使用。
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
DataContext="{StaticResource ViewModel}">
</Grid>
因为很多WPF程序都是把界面放在 Window 而不是放在页,所以为了在 UWP 和WPF使用的都是相同。可以用 FrameworkElement 代替 Page 。因为所有控件几乎都继承于 FrameworkElement 于是在页面任何地方都可以放这句话,不需要多余修改。所以刚才的
Page.Resources
就可以修改为
FrameworkElement.Resources
可是这个方法有个缺点,无法在页面 Page 元素上使用 DataContext 绑定,只能在 资源后面的 Grid 使用。因为资源是有顺序,Page 在资源之前,于是 Page 就无法绑定。在WPF的也一样。提示的错误参见下图。
如果只有一个页面,而且使用的地方也是在 页面的内容,那么建议使用这个方法。
![](https://ask.qcloudimg.com/http-save/yehe-2759138/e4y9u42bud.jpeg?imageView2/2/w/1200)
如果需要在 Page 的元素也绑定到 ViewModel ,那么可以参见下面的方法。
app 资源绑定
另一个方法是把他写到 app ,代码就是
<Application.Resources>
<viewModel:ViewModel x:Key="ViewModel"></viewModel:ViewModel>
</Application.Resources>
这样在程序任何地方都可以使用
![](https://ask.qcloudimg.com/http-save/yehe-2759138/eq77eozclk.jpeg?imageView2/2/w/1200)
我的想法,如果是 ViewModel ,那么写在这里,对于 MVVM 的 ViewModel ,MainPage 对应的 ViewModel 建议写在这里。
如果写在这,代码使用
(ViewModel) App.Current.Resources["ViewModel"]
就可以获得,也就是在任意的代码都可以使用这个方法获得。参见:
win10 uwp 后台获取资源
这个方法的优点: 在程序运行时都可以得到 ViewModel ,这是这方法适合的地方。
当然缺点是,如果你写了很多个 ViewModel 在资源,在程序运行都会占内存,也不会释放,所以一般建议只写ViewModel ,不要写多个。
DataContext 新建资源
如果对于一个 ViewModel 只有一个页面使用,那么可以不需要写在 App ,因为这样会让其它的页面都可以访问
遇到上面的需要,只有一个页面需要 ViewModel ,可以直接写
<Page.DataContext>
<vm:ViewModel></vm:ViewModel>
</Page.DataContext>
这个方法可以让ViewModel和页面都在一个时间,也就是关闭了页面,也就自动关了 ViewModel ,说了这么多,好像还没说如何在代码使用 viewModel 。上面的所有方法在代码使用 ViewModel 都相同。
后台代码获得资源
先定义属性 ViewModel ,然后在 构造写从 DataContext 转换。记得写构造函数的最后,在 InitializeComponent 的后面。
public sealed partial class MainPage : Page
public MainPage()
this.InitializeComponent();
ViewModel = (ViewModel) DataContext; //这是 cast 方法,直接转换,不要使用 as 的方法。
private ViewModel ViewModel { set; get; }
}
为何需要把 ViewModel 转换写在最后,我就不继续解释。
关于为何使用 cast 而不是 as ,因为已经确定了现在使用的类型就是 ViewModel ,我也需要使用的是 ViewModel 不是其他,如果有人改了其它的类型,我必须报错,于是就使用 cast ,如果使用了 Cast 那么看日志比较容易看到是那里写错。
代码定义资源
除了在 xaml 定义DataContext,一个常用方法是在 代码定义
public MainPage()
ViewModel = new ViewModel();
this.InitializeComponent();
DataContext = ViewModel;
private ViewModel ViewModel
set; get;
}
这个方法也是推荐的,可以在代码定义,但是这样在 xaml 写 binding 就不会有提示。
如果只在代码写新建 ViewModel ,不定义 DataContext ,把他写在 xaml ,那么就可以获得提示。
代码定义,xaml绑定
这里的 提示 指的是,在 xaml 输入的时候,写一个变量不需要完全自己写。和后台代码一样,会提示这个变量,自动给你选。没有提示容易写错代码,而且变量改名了,xaml不会随着改。
public MainPage()
ViewModel = new ViewModel();
this.InitializeComponent();