简体   繁体   English

如何在 Xamarin.UWP 的另一个内容中绑定内容?

[英]How to bind content inside another content in Xamarin.UWP?

I'm creating controls in one page that have other controls of their own.我正在一个页面中创建具有自己的其他控件的控件。 I'm trying to bind the content of a frame inside another bound content, but it crashes if I try to access it the second time.我正在尝试将框架的内容绑定到另一个绑定内容中,但是如果我第二次尝试访问它,它会崩溃。

Also tried to change bind mode to TwoWay with the same result.还尝试将绑定模式更改为 TwoWay,结果相同。

Xamarin Forms: 5.0.0.2012 Xamarin Forms:5.0.0.2012

Xamarin.Essentials: 1.6.1 Xamarin.Essentials:1.6.1

PropertyChanged.Fody: 3.3.2 PropertyChanged.Fody:3.3.2

Main Xaml ->主要 Xaml ->

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:test="clr-namespace:Test"
             x:Class="Test.MainPage">
    <ContentPage.BindingContext>
        <test:MainViewModel/>
    </ContentPage.BindingContext>
    <StackLayout>
        <Button Text="Some Content View"
                Command="{Binding ChangeToContent}"/>
        <Button Text="Some other Content View"
                Command="{Binding ChangeToOtherContent}"
                />
        <Frame Content="{Binding model.MainContent}"/>
    </StackLayout>

</ContentPage>

MainViewModel--> MainViewModel-->

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;
using Xamarin.Forms;

namespace Test
{
    public class MainViewModel : INotifyPropertyChanged
    {
        public MainModel model { get; set; } = new MainModel();

        public Command ChangeToContent => new Command(() => {
            model.MainContent.Content = new Test1Content();
            });

        public Command ChangeToOtherContent => new Command(() => {
            model.MainContent.Content = new Test2Content();
        });



        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            var changed = PropertyChanged;
            if (changed == null)
                return;

            changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
    }
}

Main Model -->主Model -->

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;
using Xamarin.Forms;

namespace Test
{
    public class MainModel : INotifyPropertyChanged
    {
        public Frame SomeContent { get; set; } = new Frame()
        {
            BackgroundColor = Color.Red,
            WidthRequest = 40,
            HeightRequest = 40
        };

        public Frame SomeOtherContent { get; set; } = new Frame()
         {
             BackgroundColor = Color.Blue,
             WidthRequest = 40,
             HeightRequest = 40
         };

        public ContentView MainContent { get; set; } = new ContentView();

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            var changed = PropertyChanged;
            if (changed == null)
                return;

            changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
    }
}

First Content View -->第一个内容视图 -->

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Test.Test1Content">
  <ContentView.Content>
      <StackLayout>
          <Label Text="This is Test 1 Content" />
            <Frame Content="{Binding model.SomeContent}"/>
        </StackLayout>
  </ContentView.Content>
</ContentView>

Second Content第二个内容

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Test.Test2Content">
  <ContentView.Content>
      <StackLayout>
          <Label Text="This is Test 2 Content" />
            <Frame Content="{Binding model.SomeOtherContent}"/>
        </StackLayout>
  </ContentView.Content>
</ContentView>

Result: https://imgur.com/a/caN9gxX结果: https://imgur.com/a/caN9gxX

  • 1st Image is the startup第一张图片是启动
  • 2nd Image is after pressing top button第二张图片是按下顶部按钮后
  • 3rd Image is after pressing the button under第三张图片是按下下面的按钮后
  • 4th Image is of the error's stack trace after pressing top button again第四张图片是再次按下顶部按钮后的错误堆栈跟踪

I may have found a solution.我可能已经找到了解决方案。 The hint was in https://github.com/xamarin/Xamarin.Forms/issues/2713 .提示在https://github.com/xamarin/Xamarin.Forms/issues/2713中。

If I modify the Command ChangeToOtherContent and ChangeToContent in my Viewmodel like this:如果我像这样在 Viewmodel 中修改 Command ChangeToOtherContent 和 ChangeToContent :


        public Command ChangeToContent => new Command(() => {
            model.MainContent.Content = null;
            model.MainContent.Content = new Test1Content() { BindingContext = this };
            });

        public Command ChangeToOtherContent => new Command(() => {
            model.MainContent.Content = null;
            model.MainContent.Content = new Test2Content() { BindingContext = this };
        });

the app doesn't crash.该应用程序不会崩溃。

The null content is important if I trigger the command successively.如果我连续触发命令,null 内容很重要。 It can probably be replaced by a bool, testing if the user has triggered the command more than once, but that would imply a lot more tests.它可能可以用布尔值代替,测试用户是否多次触发命令,但这意味着更多的测试。

I don't understand why the bindingcontext needs to be added, as it is correct the first time it gets rendered.我不明白为什么需要添加 bindingcontext,因为它在第一次渲染时是正确的。 Maybe someone can add to this.也许有人可以添加到这一点。

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

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