C# 表单:跳过自定义ContentView上绑定中的源

C# 表单:跳过自定义ContentView上绑定中的源,c#,xamarin.forms,binding,custom-view,C#,Xamarin.forms,Binding,Custom View,我正在尝试创建一个包含复选框和标签的ContentView。单击标签时,应切换复选框 现在,我的代码存在的问题是,每次要使用复选框时,都必须重新设置BindingContext的基础,否则它将无法工作 您必须指定源(=MainPage.BindingContext): 因此,他在我的复选框中查找PanelsVisible属性,而不是我的viewmodel(为什么?) 我如何重写它,使我不必每次使用复选框时都指定源 我创造了一个 代码 代码隐藏: [XamlCompilation(XamlComp

我正在尝试创建一个包含
复选框和
标签的ContentView。单击标签时,应切换复选框

现在,我的代码存在的问题是,每次要使用复选框时,都必须重新设置BindingContext的基础,否则它将无法工作

您必须指定源(=MainPage.BindingContext):

因此,他在我的复选框中查找
PanelsVisible
属性,而不是我的viewmodel(为什么?)

我如何重写它,使我不必每次使用复选框时都指定源

我创造了一个

代码 代码隐藏:

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CheckBox : ContentView
{
    public CheckBox()
    {
        InitializeComponent();
        BindingContext = this;
    }

    #region IsChecked
    public static readonly BindableProperty IsCheckedProperty = BindableProperty.Create("IsChecked", typeof(bool), typeof(CheckBox), false, BindingMode.TwoWay, propertyChanged: (bindable, oldValue, newValue) =>
    {
        var control = (CheckBox)bindable;
        control.IsChecked = (bool)newValue;
    });

    public bool IsChecked
    {
        get => (bool)GetValue(IsCheckedProperty);
        set
        {
            SetValue(IsCheckedProperty, value);
        }
    }
    #endregion

    #region Text
    public static readonly BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(CheckBox), "", BindingMode.OneWay, propertyChanged: (bindable, oldValue, newValue) =>
    {
        var control = (CheckBox)bindable;
        control.Text = (string)newValue;
    });

    public string Text
    {
        get => (string)GetValue(TextProperty);
        set => SetValue(TextProperty, value);
    }
    #endregion

    private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
    {
        IsChecked = !IsChecked;
    }
}
Xaml:


在自定义控件XAML文件中,注意标记

因此,在自定义控件构造函数中,请更改为
Content.BindingContext=this

然后它就起作用了


顺便说一句,稍微重构一下IsChecked区域

  • 当您绑定到它自己,并且对属性没有任何更改时,您可以忽略该部分
  • 使用“nameof(IsChecked)”而不是字符串值

  • 谢谢
    Content.BindingContext=这是为我做的。而且,
    propertyChanged
    回调不再像您所说的那样必要
    <controls:CheckBox
        Text="Hello world"
        IsChecked="{Binding PanelsVisible, Mode=TwoWay}" />
    
    [0:] Binding: 'PanelsVisible' property not found on 'Example.Xamarin.Forms.Controls.CheckBox', target property: 'Example.Xamarin.Forms.Controls.CheckBox.IsChecked'
    
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class CheckBox : ContentView
    {
        public CheckBox()
        {
            InitializeComponent();
            BindingContext = this;
        }
    
        #region IsChecked
        public static readonly BindableProperty IsCheckedProperty = BindableProperty.Create("IsChecked", typeof(bool), typeof(CheckBox), false, BindingMode.TwoWay, propertyChanged: (bindable, oldValue, newValue) =>
        {
            var control = (CheckBox)bindable;
            control.IsChecked = (bool)newValue;
        });
    
        public bool IsChecked
        {
            get => (bool)GetValue(IsCheckedProperty);
            set
            {
                SetValue(IsCheckedProperty, value);
            }
        }
        #endregion
    
        #region Text
        public static readonly BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(CheckBox), "", BindingMode.OneWay, propertyChanged: (bindable, oldValue, newValue) =>
        {
            var control = (CheckBox)bindable;
            control.Text = (string)newValue;
        });
    
        public string Text
        {
            get => (string)GetValue(TextProperty);
            set => SetValue(TextProperty, value);
        }
        #endregion
    
        private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
        {
            IsChecked = !IsChecked;
        }
    }
    
    <?xml version="1.0" encoding="UTF-8"?>
    <ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:d="http://xamarin.com/schemas/2014/forms/design"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                 xmlns:controls="clr-namespace:MintPlayer.Xamarin.Forms.Controls"
             
                 mc:Ignorable="d"
                 d:BindingContext="{x:Static controls:CheckBox}"
             
                 x:Class="MintPlayer.Xamarin.Forms.Controls.CheckBox">
        <ContentView.Content>
            <StackLayout Orientation="Horizontal">
                <CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay, UpdateSourceEventName=CheckedChanged}" HorizontalOptions="Start" VerticalOptions="Start" />
                <Label Text="{Binding Text}" Padding="0,5,0,0" HorizontalOptions="StartAndExpand" VerticalOptions="Start">
                    <Label.GestureRecognizers>
                        <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped" />
                    </Label.GestureRecognizers>
                </Label>
            </StackLayout>
        </ContentView.Content>
    </ContentView>
    
    <?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:app="clr-namespace:MintPlayer.Xamarin.Forms.Controls.Demo"
                 xmlns:controls="clr-namespace:MintPlayer.Xamarin.Forms.Controls;assembly=MintPlayer.Xamarin.Forms.Controls"
                 x:Class="MintPlayer.Xamarin.Forms.Controls.Demo.MainPage">
        <ContentPage.BindingContext>
            <app:MainVM />
        </ContentPage.BindingContext>
        <StackLayout>
            <controls:CheckBox Text="Hello world" IsChecked="{Binding BindingContext.PanelsVisible, Source={RelativeSource Mode=FindAncestor, AncestorType={x:Type app:MainPage}}, Mode=TwoWay}" />
            <!-- I want to write this -->
            <!-- <controls:CheckBox Text="Hello world" IsChecked="{Binding PanelsVisible, Mode=TwoWay}" /> -->
            <Switch IsToggled="{Binding PanelsVisible, Mode=TwoWay}" />
            <Frame IsVisible="{Binding PanelsVisible}" BackgroundColor="#2196F3" Padding="24" CornerRadius="0">
                <Label Text="Welcome to Xamarin.Forms!" HorizontalTextAlignment="Center" TextColor="White" FontSize="36"/>
            </Frame>
        </StackLayout>
    </ContentPage>
    
    public class MainVM : BaseModel
    {
        private bool panelsVisible;
        public bool PanelsVisible
        {
            get => panelsVisible;
            set => SetProperty(ref panelsVisible, value);
        }
    }
    
            #region IsChecked
            public static readonly BindableProperty IsCheckedProperty = BindableProperty.Create(nameof(IsChecked), typeof(bool), typeof(CheckBox), false, BindingMode.TwoWay);
    
            public bool IsChecked
            {
                get => (bool)GetValue(IsCheckedProperty);
                set => SetValue(IsCheckedProperty, value);
            }
            #endregion