बाइंडिंग के साथ कस्टम दृश्य का उपयोग करते समय मुझे "निर्दिष्ट कास्ट वैलिड नहीं है" क्यों मिलता है, लेकिन जब मैं मैन्युअल रूप से सेट नहीं करता हूं?

Aug 17 2020

मैं एक अवलोकन दृश्य का उपयोग करके एक BindableProperty के रूप में एक अवलोकन दृश्य का निर्माण कर रहा हूं (मेरा लक्ष्य इसकी सामग्री के आधार पर दृश्य के प्रारूप को अद्यतन करना था, इस मामले में रंगों की एक सूची)। मुझे लगता है कि मेरे पास कस्टम दृश्य में ठीक से सेट की गई संपत्ति है। यदि मैं C # में बाइंड करने योग्य संपत्ति सेट करता हूं, तो यह काम करता है। अगर मैं XAML के अंदर {Binding varname} का उपयोग करने का प्रयास करता हूं, तो यह "निर्दिष्ट कास्ट मान्य नहीं है" त्रुटि फेंकता है। मैं यह पता लगाने की कोशिश कर रहा हूं कि मेरा मुद्दा कहां है।

नीचे सार्वजनिक मेनपेज () में आप टिप्पणी की गई लाइन देख सकते हैं जहाँ मैंने संपत्ति को मैन्युअल रूप से सेट किया है। अगर मैं इसे अनसुना कर देता हूं और MainPage.xaml से "कलर = {बाइंडिंग टेस्ट}" लेता हूं, तो सब कुछ काम करता है। अगर मैं इसे चलाता हूं, तो मुझे इसका अपवाद मिलेगा।

यहाँ मेरे सभी कोड है:

MainPage.xaml.cs

public partial class MainPage : ContentPage
{
    public ObservableCollection<Color> Test { get; set; }
    public MainPage()
    {
        Test = new ObservableCollection<Color>();

        Test.Add(Color.Blue);
        Test.Add(Color.Green);
        Test.Add(Color.Red);
        Test.Add(Color.Purple);
        
        this.BindingContext = this;
        InitializeComponent();

        //myView.Colors = Test;
    }

    

    private void OnClicked(object sender, EventArgs e)
    {
        myView.Colors.Add(Color.Yellow);
    }
}

MainPage.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:local="clr-namespace:ColorBoxes"
         x:Class="ColorBoxes.MainPage">

    <StackLayout HorizontalOptions="CenterAndExpand">
        <local:ColorBoxView  x:Name="myView" Colors="{Binding Test}" WidthRequest="400" HeightRequest="600"/>
        <Button Text="Add Color" Clicked="OnClicked"/>
    </StackLayout>

</ContentPage>

ColorBoxView.xaml.cs

public partial class ColorBoxView : ContentView
{
    public ColorBoxView()
    {
       InitializeComponent();
       
    }
    
    public static BindableProperty ColorList = BindableProperty.Create(
        propertyName: "Colors",
        returnType: typeof(ObservableCollection<Color>),
        declaringType: typeof(ColorBoxView),
        defaultValue: new ObservableCollection<Color>(),
        defaultBindingMode: BindingMode.OneWay,
        propertyChanged: HandleColorListPropertyChanged
    );

    public ObservableCollection<Color> Colors
    {
        get { return (ObservableCollection<Color>) base.GetValue(ColorList); }
        set
        {
            if (value != this.Colors)
            {
                base.SetValue(ColorList, value);
                Colors.CollectionChanged += Items_CollectionChanged;
            }
        }
    }
   
    
    void Items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        buildView(Colors);
    }

    private void buildView(ObservableCollection<Color> newColors)
    {
        /* This code is never reached */
    }
    private static void HandleColorListPropertyChanged(BindableObject bindable, object oldValue, object newValue)
    {
        ObservableCollection<Color> newColors = (ObservableCollection<Color>) newValue;
        ColorBoxView thisView = (ColorBoxView) bindable;

        thisView.buildView(newColors);
        
    }

ColorBoxView.xaml

<?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="ColorBoxes.ColorBoxView" >

    <Grid  x:Name="BoxGrid"  HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" 
           RowSpacing="0" ColumnSpacing="0" Padding="0">
    </Grid>

</ContentView>

स्टैक ट्रेस:

System.InvalidCastException: Specified cast is not valid. 
   at ColorBoxes.MainPage.InitializeComponent () [0x00023] in /Users/docmani/RiderProjects/ColorBoxes/ColorBoxes/ColorBoxes/obj/Debug/netstandard2.0/MainPage.xaml.g.cs:26
   at ColorBoxes.MainPage..ctor () [0x00060] in /Users/docmani/RiderProjects/ColorBoxes/ColorBoxes/ColorBoxes/MainPage.xaml.cs:25
   at ColorBoxes.App..ctor () [0x0000f] in /Users/docmani/RiderProjects/ColorBoxes/ColorBoxes/ColorBoxes/App.xaml.cs:15
   at ColorBoxes.iOS.AppDelegate.FinishedLaunching (UIKit.UIApplication app, Foundation.NSDictionary options) [0x00007] in /Users/docmani/RiderProjects/ColorBoxes/ColorBoxes/ColorBoxes.iOS/AppDelegate.cs:25
   at at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain(int,string[],intptr,intptr)
   at UIKit.UIApplication.Main (System.String[] args, System.IntPtr principal, System.IntPtr delegate) [0x00005] in /Library/Frameworks/Xamarin.iOS.framework/Versions/13.18.2.1/src/Xamarin.iOS/UIKit/UIApplication.cs:86
   at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0000e] in /Library/Frameworks/Xamarin.iOS.framework/Versions/13.18.2.1/src/Xamarin.iOS/UIKit/UIApplication.cs:65
   at ColorBoxes.iOS.Application.Main (System.String[] args) [0x00001] in /Users/docmani/RiderProjects/ColorBoxes/ColorBoxes/ColorBoxes.iOS/Main.cs:16

अतिरिक्त जानकारी - मैंने XGarin को अपग्रेड करने की कोशिश की। NuGet में यह थोड़ी देर से थी। अब यह बाध्यकारी के साथ भी संकलित नहीं होगा। यह मुझे देता है:

 MainPage.xaml(9, 46): [XFC0009] No property, BindableProperty, or event found for "Colors", or mismatching type between value and property.

लेकिन फिर, अगर मैं C # में मान को मैन्युअल रूप से सेट करता हूं तो यह अभी भी काम करता है। मैं निश्चित रूप से अपने एक्सएएमएल में कुछ याद कर रहा हूं, लेकिन मुझे नहीं पता कि यह क्या है।

जवाब

LeonLu-MSFT Aug 17 2020 at 10:16

आप BindablePropertyनिम्न को बदल सकते हैं ColorListProperty, फिर xaml में एक परीक्षण करें।

public partial class ColorBoxView : ContentView
    {
        public ColorBoxView ()
        {
            InitializeComponent ();
        }
 
        public static readonly BindableProperty ColorListProperty = BindableProperty.Create(
            nameof(ColorList), 
            typeof(ObservableCollection<object>), 
            typeof(ColorBoxView), 
            new ObservableCollection<object>(), 
            BindingMode.OneWay, 
            propertyChanged: ContractListPropertyChangedDelegate);
        public ObservableCollection<object> ColorList
        {
            get =>
            (ObservableCollection<object>)GetValue(ColorListProperty);
            set => SetValue(ColorListProperty, value);
        }
        private static void ContractListPropertyChangedDelegate(BindableObject bindable, object oldValue, object newValue)
        {
            // throw new NotImplementedException();
         //   ColorBoxView colorBoxView= bindable as ColorBoxView;


        }
 <local:ColorBoxView  x:Name="myView" ColorList="{Binding Test}"  WidthRequest="400" HeightRequest="600"/>

यदि आप CollectionChangedबटन को क्लिक करने के लिए ईवेंट को निष्पादित करना चाहते हैं , तो आप 's कंस्ट्रक्टर ColorList.CollectionChanged += ColorList_CollectionChangedमें जोड़ सकते हैं ColorBoxView

public ColorBoxView ()
        {
            InitializeComponent ();
            ColorList.CollectionChanged += ColorList_CollectionChanged;

        }

        private void ColorList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
           // throw new NotImplementedException();
        }

setजब आप एक नया सेट करते हैं, तो आपकी विधि निष्पादित की जाएगी ObservableCollection, यदि आप आइटम को अस्तित्व में जोड़ते हैं ObservableCollection, CollectionChangedतो ColorBoxViewशायद बेहतर में उपयोग करें ।

BTGraham Aug 17 2020 at 20:33

इसलिए कई खोजों के बाद मुझे कई उदाहरण मिले जहां बाइंडप्रोपरेटी का प्रकार 'IEnumerable' पर सेट किया गया था। अपना कोड रिड्यू करने के बाद, मैं निम्नलिखित काम करता हूं:

public partial class ColorBoxView : ContentView
{
    public ColorBoxView()
    {
       InitializeComponent();
    }
    
    public static readonly BindableProperty ColorsProperty =
        BindableProperty.Create (nameof (Colors), typeof (IEnumerable), typeof (ColorBoxView), null,
            BindingMode.Default, null, HandleColorListPropertyChanged);

    public IEnumerable Colors
    {
        get { return (IEnumerable) GetValue (ColorsProperty); }
        set
        {
            SetValue (ColorsProperty, value);
            var oc = (ObservableCollection<Color>) (this.Colors);
            oc.CollectionChanged += Items_CollectionChanged;
        }
    }

    private void Items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        buildView( (ObservableCollection<Color>)Colors);
    }

    private void buildView(ObservableCollection<Color> newColors)
    {
        /* Update code */
    }

    private static void HandleColorListPropertyChanged(BindableObject bindable, object oldValue, object newValue)
    {
        ObservableCollection<Color> newColors = (ObservableCollection<Color>) newValue;
        ColorBoxView thisView = (ColorBoxView) bindable;

        thisView.Colors = newColors;
        thisView.buildView(newColors);

    }

}

मुझे आधिकारिक कारण जानने में बहुत दिलचस्पी होगी कि यह क्यों काम करता है। टिप्पणियों की सराहना की जाती है।