Свойство привязки Xamarin базового представления

У меня есть базовое представление XAML, в котором есть настраиваемый элемент управления с привязываемым свойством, который используется для отображения/скрытия элемента управления Grid. Мне нужно изменить это свойство из представления XAML, которое наследуется от базового представления.

представление пользовательского элемента управления

using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using Syncfusion.SfBusyIndicator.XForms;
using System.Runtime.CompilerServices;

namespace TEST_SF
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class VolosLoading : ContentView
{
    private static Grid _LoadingContainer = null;

    public bool Mostra
    {
        get { return (bool)GetValue(MostraProperty); }
        set { SetValue(MostraProperty, value); OnPropertyChanged(nameof(Mostra)); }
    }

    public static BindableProperty MostraProperty = BindableProperty.Create(
       propertyName: nameof(Mostra),
       returnType: typeof(bool),
       declaringType: typeof(VolosLoading),
       defaultValue: false,
       defaultBindingMode: BindingMode.TwoWay
       , propertyChanged: MostraPropertyChanged
   );

    private static void MostraPropertyChanged(BindableObject bindable, object oldValue, object newValue)
    {

        _LoadingContainer.IsEnabled = (bool)newValue;
        _LoadingContainer.IsVisible = (bool)newValue;
    }

    public VolosLoading()
    {
        InitializeComponent();
        _LoadingContainer = (Grid)FindByName("LoadingContainer");
        OnPropertyChanged(nameof(Mostra));
    }
 }
}

его представление

<?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:busyindicator="clr-namespace:Syncfusion.SfBusyIndicator.XForms;assembly=Syncfusion.SfBusyIndicator.XForms"
    x:Class="TEST_SF.VolosLoading">

    <ContentView.Content>        
        <Grid x:Name="LoadingContainer" IsEnabled="{Binding Mostra}" IsVisible="{Binding Mostra}">            
            <Grid BackgroundColor="LightGray" Opacity="0.6" />
            <busyindicator:SfBusyIndicator x:Name="Loading" AnimationType="DoubleCircle" 
                                           ViewBoxWidth="150" ViewBoxHeight="150" 
                                           TextColor="Green" BackgroundColor="Transparent"  
                                           HorizontalOptions="Center" VerticalOptions="Center" />
        </Grid>
    </ContentView.Content>

</ContentView>

базовый класс

   namespace TEST_SF.Base
    {
      public class BaseClass
      {
          public static VolosLoading PageLoading = new VolosLoading { Mostra = false };
      }
    }

базовый вид

 <?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:local="clr-namespace:TEST_SF"
             x:Class="TEST_SF.BasePage">
    <ContentPage.ControlTemplate>
        <ControlTemplate>
            <StackLayout>
                <Label BackgroundColor="Red" Text="Welcome to Xamarin.Forms!"
                    VerticalOptions="StartAndExpand" 
                    HorizontalOptions="CenterAndExpand" />
                <local:VolosLoading></local:VolosLoading>

                <ContentPresenter></ContentPresenter>

            </StackLayout>
        </ControlTemplate>

    </ContentPage.ControlTemplate>
    </ContentPage>

Затем у меня есть представление, которое наследуется от базового представления с кнопкой, которая вызывает команду, выполняющую этот код:

PageLoading.Mostra = !PageLoading.Mostra;

Класс:

class MainPage_Repo : Base.BaseClass

его вид:

 <local:BasePage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:TEST_SF"
             x:Class="TEST_SF.MainPage">

        <ContentPage.BindingContext>
            <local:MainPage_Repo />
        </ContentPage.BindingContext>

            <StackLayout>
                <Button VerticalOptions="Center" HorizontalOptions="Center" Text="Loading SF" Command="{Binding MyMockCommand}" CommandParameter="1" />
            </StackLayout>
    </local:BasePage>

Проблемы в том что Grid видно при запуске, а при нажатии на кнопку ничего не меняется, значение Mostra меняется правильно но сам Grid виден всегда.

Как я могу это решить?


person Hikari    schedule 29.01.2019    source источник


Ответы (2)


Если у вас есть статические свойства в ContentView, могут возникнуть странные проблемы, поскольку они являются общими для разных экземпляров, в вашем случае это относится к _LoadingContainer

Даже если это не решит вашу проблему, это может вызвать огромные проблемы, и этого делать не следует.

person Ivan Ičin    schedule 29.01.2019

Проблема в том, что когда вы звоните:

_LoadingContainer = (Grid)FindByName("LoadingContainer");

Эта строка создает копию контейнера Grid, определенного в XAML с помощью x:Name="LoadingContainer". Затем, когда свойство Mostra изменяется, вы делаете:

_LoadingContainer.IsEnabled = (bool)newValue;
_LoadingContainer.IsVisible = (bool)newValue;

Вышеупомянутое относится к доступу и изменению свойств копии представления Grid, а не самого LoadingContainer.

Замените все экземпляры _LoadingContainer на LoadingContainer, и ваша проблема должна быть решена.

Кроме того, вы можете удалить привязки к свойствам IsVisible и IsEnabled файла Grid. Это вызовет ненужную сложность в скомпилированном коде.

ИЗМЕНИТЬ

Кроме того, в вашем обработчике MostraPropertyChanged вы должны изменить его на следующее:

private static void MostraPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
    var control = (VolosLoading)bindable;
    if (control != null)
    {
        control.LoadingContainer.IsEnabled = (bool)newValue;
        control.LoadingContainer.IsVisible = (bool)newValue;
    }
}
person Tom    schedule 29.01.2019
comment
Спасибо, но я не могу заменить все экземпляры _LoadingContainer на LoadingContainer, потому что внутри метода MostraPropertyChanged LoadingContainer не существует. Я хотел бы использовать привязку для IsVisible и IsEnabled внутри представления XMAL. - person Hikari; 29.01.2019
comment
Я добавил правку в свой ответ, которая должна охватывать это. Вы можете получить доступ к содержимому XAML, обратившись к BindableObject в качестве элемента управления. - person Tom; 29.01.2019
comment
Спасибо, но это не работает. Я также пытался добавить «BindingContext = this» после InitializeComponent(), но не работает. - person Hikari; 29.01.2019