简体   繁体   English

使用模板10在UWP用户控件中进行数据绑定

[英]Data Binding in UWP User Controls using Template 10

I cannot get binding to work in my app with a user control. 我无法使用用户控件在我的应用程序中工作。 It is a UWP app with template 10. 它是一个带有模板10的UWP应用程序。

I use the same bind in the mainpage as I do in the user control but the field in the user control does not react to changes. 我在主页中使用与用户控件中相同的绑定,但用户控件中的字段不会对更改做出反应。 I have read several articles that tell me how to set the datacontent of my user control but I can not get any of them to work. 我已经阅读了几篇文章,告诉我如何设置我的用户控件的datacontent,但我不能让它们中的任何一个工作。

My code is as follows: 我的代码如下:

Mainpage.xaml MainPage.xaml中

    Page x:Class="UserControlTest.Views.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
      xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
      xmlns:controls="using:Template10.Controls"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:local="using:UserControlTest.Views"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:vm="using:UserControlTest.ViewModels" mc:Ignorable="d">

    <Page.DataContext>
        <vm:MainPageViewModel x:Name="ViewModel" />
    </Page.DataContext>

    <RelativePanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

        <controls:PageHeader x:Name="pageHeader" Content="Main Page"
                             RelativePanel.AlignLeftWithPanel="True"
                             RelativePanel.AlignRightWithPanel="True"
                             RelativePanel.AlignTopWithPanel="True" />

        <TextBlock x:Name="mainTextBlock" Margin="16,16,16,16"
                   RelativePanel.AlignLeftWithPanel="True"
                   RelativePanel.Below="pageHeader" 
                   Text="{Binding TextToShow}" />

        <local:ShowText Margin="16,16,16,16"
            RelativePanel.Below="pageHeader"
            RelativePanel.AlignRightWithPanel="True"/>

        <Button Content="Change Text" Margin="16,16,16,16" 
                Command="{x:Bind ViewModel.ChangeText }" 
                RelativePanel.AlignLeftWithPanel="True" 
                RelativePanel.Below="mainTextBlock"/>
    </RelativePanel>

</Page>

MainPageViewModel.cs MainPageViewModel.cs

    using System.Collections.Generic;
    using System;
    using System.Linq;
    using System.Threading.Tasks;
    using Windows.Security.Cryptography.Core;
    using Template10.Mvvm;
    using Template10.Services.NavigationService;
    using Windows.UI.Xaml.Navigation;

    namespace UserControlTest.ViewModels
    {
    public class MainPageViewModel : ViewModelBase
    {
        private string _textToShow = "Initial text";

        public string TextToShow
        {
            get { return _textToShow; }
            set { Set(ref _textToShow, value); }
        }

        DelegateCommand _changeText;

        public DelegateCommand ChangeText
            => _changeText ?? (_changeText = new DelegateCommand(ExecuteChangeTest, CanChangeText));

        private void ExecuteChangeTest()
        {
            TextToShow = "Changed text";
        }

        private bool CanChangeText()
        {
            return true;
        }
    }
}

ShowText.xaml ShowText.xaml

   <UserControl
    x:Class="UserControlTest.Views.ShowText"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UserControlTest.Views"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:vm="using:UserControlTest.ViewModels" mc:Ignorable="d">

    <UserControl.DataContext>
        <vm:MainPageViewModel x:Name="ViewModel" />
    </UserControl.DataContext>

    <Grid>
        <TextBlock x:Name="UserControlTextBlock"  
                   Text="{Binding TextToShow}" />
    </Grid>
</UserControl>

At first glance the problem is that your UserControl and your MainPage are using two different instances of ViewModel. 乍一看,问题是您的UserControl和您的MainPage正在使用两个不同的ViewModel实例。 When you create your static resource 创建静态资源时

        <vm:MainPageViewModel x:Name="ViewModel" />

You're creating an instance of MainPageViewModel. 您正在创建MainPageViewModel的实例。 This means that when you set the value in from your MainPage instance of MainPageViewModel, it's not propagating to the second instance of MainPageViewModel that your UserControl created. 这意味着当您从MainPageViewModel的MainPage实例设置值时,它不会传播到您的UserControl创建的第二个MainPageViewModel实例。

No worries though, we can fix this. 不用担心,我们可以解决这个问题。

The DataContext of your user control should be set automatically to its parent's DataContext. 应将用户控件的DataContext自动设置为其父级的DataContext。

So Let's assume for a moment that you use your UserControl in your MainPage.xaml 因此,让我们暂时假设您在MainPage.xaml中使用UserControl

 <Page.DataContext>
    <vm:MainPageViewModel x:Name="ViewModel" />
 </Page.DataContext>

 <MyUserControls:MyUserControl />

In this instance, MyUsercontrol is using the MainPageViewModel as it's DataContext. 在这个例子中,MyUsercontrol使用MainPageViewModel作为它的DataContext。 HOWEVER, this probably won't work, it's not a finished solution. 但是,这可能不起作用,它不是一个完成的解决方案。

What you need to do is go to your UserControl's Xaml.CS and create a dependency property that you can bind to. 您需要做的是转到UserControl的Xaml.CS并创建一个可以绑定的依赖项属性。

 public class MyUserControl : Control{

    public string MyControlsText
    {
        get { return (string)GetValue(MyControlsTextProperty); }
        set { SetValue(MyControlsTextProperty, value); }
    }

    public static readonly DependencyProperty MyControlsTextProperty = 
             DependencyProperty.Register("MyControlsText", typeof(string), 
                typeof(MyUserControl), new PropertyMetadata(String.Empty)); 

    }

Now that we have our dependency property, in our UserControl's Xaml we can bind to it. 现在我们有了依赖属性,在UserControl的Xaml中我们可以绑定它。

<Grid>
    <TextBlock x:Name="UserControlTextBlock"  
               Text="{Binding MyControlsText}" />
</Grid>

And finally in our MainPage.Xaml we can finalize the binding 最后在我们的MainPage.Xaml中,我们可以完成绑定

 <MyUserControls:MyUserControl MyControlsText="{Binding TextToShow}" />

So with the above code here is what we are accomplishing: 所以使用上面的代码就是我们正在完成的事情:

  • The DataContext is set in the MainPage.xaml and all of the children of MainPage.xaml share this DataContext DataContext在MainPage.xaml中设置,MainPage.xaml的所有子项共享此DataContext
  • We created a dependency property in our UserControl that we can bind to 我们在UserControl中创建了一个可以绑定的依赖属性
  • We bind the XAML of our UserControl to our dependency property 我们将UserControl的XAML绑定到依赖属性
  • We Bind our view model's text property to our new user controls dependency property. 我们将视图模型的text属性绑定到新的用户控件依赖项属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM