【问题标题】:x:Bind and nested class in a UWP applicationx:UWP 应用程序中的绑定和嵌套类
【发布时间】:2016-02-07 18:10:23
【问题描述】:

我目前正在开发一个 UWP 应用程序,我想使用已编译的绑定系统。

我有一个扩展 Windows.UI.Xaml.Controls.Page 的基础,其中包含一个属性 ViewModel。

这里是ViewModel属性的基类:

 public class BaseViewModel : INotifyPropertyChanged
 {

    public event PropertyChangedEventHandler PropertyChanged;

    protected void RaiseOnPropertyChanged([CallerMemberName] string propertyName = "")
    {
      OnPropertyChanged(propertyName);
    }

    public void OnPropertyChanged(string propertyName)
    {
      if (PropertyChanged != null)
      {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
      }
    }

  }

这里是我的基本页面:

public abstract class BasePage : Page
{

  public BaseViewModel ViewModel { get; set; }

}

我的应用程序的页面扩展了 BasePage 并包含一个扩展 BaseViewModel 类的嵌套(内部)类。这是一个示例代码:

public sealed partial class MyPage : BasePage
{

  public sealed class MyViewModel : BaseViewModel
  {

      public string Title
      {
        get
        {
          return "Test";
        }
      }

    }

    public MyPage()
    {
      InitializeComponent();
      ViewModel = MyViewModel();
    }
}

现在,我想将 MyViewModel 类的属性 Title 绑定到我的 UI。根据this article 和this one,这样的东西应该可以工作:

<TextBlock 
  Text="{x:Bind ViewModel.(namespace:MyPage+MyViewModel.Title)}"  
/>

很遗憾,我无法编译。由于“+”字符,生成的文件MyPage.g.cs 有几个错误。您知道 UWP 应用程序是否支持嵌套(内部)类的绑定?也许它仅在 WPF 应用程序上受支持? :(

感谢您的帮助!

【问题讨论】:

  • 你试过简单写{x:Bind ViewModel.Title}吗?
  • @KooKiz :是的,我试过了,但是我有一个编译错误。找不到类型 BaseViewModel 的属性 Title。这就是我选择MyViewModel 的原因。如果我在一个单独的文件中定义我的 MyViewModel 类,则演员表工作正常。我只在MyViewModel 类是嵌套类时遇到问题。所以从技术上讲,我知道解决方法,但我喜欢嵌套类,所以我想尝试使用嵌套类:D

标签: c# xaml mvvm uwp


【解决方案1】:

在{x:Bind} 中使用“+”字符进行转换时出现了一些问题。在 MyPage.xaml 中使用 {x:Bind ViewModel.(local:MyPage+MyViewModel.Title)} 时,它会在 MyPage.g.cs 中生成如下代码来更新绑定数据:

private void Update_ViewModel(global::UWP.BaseViewModel obj, int phase)
{
    if (obj != null)
    {
        if ((phase & (NOT_PHASED | (1 << 0))) != 0)
        {
            this.Update_ViewModel__local_MyPage+MyViewModel_Title_(((global::UWP.MyPage.MyViewModel)(obj)).Title, phase);
        }
    }
}
private void Update_ViewModel__local_MyPage+MyViewModel_Title_(global::System.String obj, int phase)
{
    if((phase & ((1 << 0) | NOT_PHASED )) != 0)
    {
        XamlBindingSetters.Set_Windows_UI_Xaml_Controls_TextBlock_Text(this.obj2, obj, null);
    }
}

虽然生成的演员表是对的,但是方法名Update_ViewModel__local_MyPage+MyViewModel_Title_是无效的。所以目前不支持在{x:Bind} 中强制转换嵌套类。

如果你想使用{x:Bind},你可以使用MyViewModel而不是BaseViewModel,如下所示,效果很好。

在代码隐藏中:

public sealed partial class MyPage : BasePage
{
    public MyViewModel myViewModel;

    public sealed class MyViewModel : BaseViewModel
    {
        public string Title
        {
            get
            {
                return "Test";
            }
        }
    }

    public MyPage()
    {
        InitializeComponent();
        myViewModel = new MyViewModel();
    }
}

在 XAML 中:

<TextBlock Text="{x:Bind myViewModel.Title}" />

另外,如果您想使用BaseViewModel,您可以使用{Binding} 而不是{x:Bind},因为{Binding} 使用通用运行时对象检查。

在代码隐藏中:

public sealed partial class MyPage : BasePage
{
    public sealed class MyViewModel : BaseViewModel
    {
        public string Title
        {
            get
            {
                return "Test";
            }
        }
    }

    public MyPage()
    {
        InitializeComponent();
        ViewModel = new MyViewModel();
        this.DataContext = this;
    }
}

在 XAML 中:

<TextBlock Text="{Binding ViewModel.Title}" />

【讨论】:

    【解决方案2】:

    解决方案是使用新属性以避免强制转换和嵌套类访问 XAML 文件。所以解决方案是使用类似的东西:

    public sealed partial class MainPage : BasePage
    {
    
      public sealed class MyViewModel : BaseViewModel
      {
        public string Title
        {
          get
          {
            return "Test";
          }
        }
      }
    
      public MyViewModel LocalViewModel
      {
        get
        {
          return (MyViewModel) ViewModel;
        }
      }
    
      public MainPage()
      {
        this.InitializeComponent();
        ViewModel = new MyViewModel();
      }
    }
    

    因此,使用x:Bind 语法,XAML 看起来像:

    <TextBlock Text="{x:Bind LocalViewModel.Title}" />
    

    【讨论】:

      猜你喜欢
      • 2022-10-14
      • 2021-01-19
      • 1970-01-01
      • 1970-01-01
      • 2017-11-22
      • 1970-01-01
      • 1970-01-01
      • 2013-06-25
      • 1970-01-01
      相关资源
      最近更新 更多