Data binding to dictionary object

Hi,
I'm creating forms with the code. I want to bind the controls on the form with dictionary keys. Is this can be done with Xamarin forms. Please help with some some sample code.

Thanks

Posts

  • Hi Mark,
    Thanks for your reply. It helped me. I was just wondering why I need to raise a notification when the items are added in the dictionary. I only want to get notification when a particular item in the dictionary gets changed. This is the approach that I've taken.
    1) Created a GenericViewModel class by implementing INotifyPropertyChanged interface
    2) Added the property of type IDictionary<string,object> and raised the changed event on the setter.
    3) Apply the BindingContext from this view. See the code

    var formFields = new Dictionary<string, object>();
    
                // preparing the data binding object for the form
                foreach (var field in formSchema.form_fields)
                {
                    formFields[field.field_title] = field.field_value;
                }
    
                var bindingcontext = new GenericViewModel { FormData = formFields };
                this.BindingContext = bindingcontext.FormData;
    

    Then binded the controls

    foreach (var field in formSchema.form_fields)
                {
                    switch (field.field_type)
                    {
                        case "textfield":
                            // generate the label and text box
                            label = new Label { Text = field.field_title };
                            stackLayout.Children.Add(label);
                            textbox = new Entry();
                            textbox.SetBinding(Entry.TextProperty, string.Format("[{0}]", field.field_title));
                            stackLayout.Children.Add(textbox);
                            break;
    

    It works as expected.

  • MarkSmith.8123MarkSmith.8123 USXamarin Team, University, XamUProfessors Xamurai

    The reason is if you add a key LATER that happens to match a binding. I.e. if the app is started with a set of bindings to keys in the dictionary, and you at some later point populate those keys from some async data source that comes down after the app is up. The PropertyChanged notification would trip the binding so it would see the matching addition and bind to it.

    By the way, there was a slight bug in my ObservableDictionary - it's corrected now, but you want to make sure to raise PropertyChange with the value: "Item[Key]" for the binding to pick it up. So, in the dictionary code:

    void OnKeyAddedRemovedUpdated(string key)
    {
        PropertyChanged(this, new PropertyChangedEventArgs("Item[" + key + "]");
    }
    
  • AllanRitchie-oldAllanRitchie-old CAInsider ✭✭✭

    Observable dictionaries don't work very well at all with the latest version. Anytime I remove or update a key, the crash below happens. I've also noticed that nothing is hooking up to the PropertyChanged event (not that this would

    Unhandled managed exception: Object reference not set to an instance of an object (System.NullReferenceException)
    at Xamarin.Forms.Platform.iOS.ListViewRenderer.UpdateItems (System.Collections.Specialized.NotifyCollectionChangedEventArgs e, Int32 section, Boolean resetWhenGrouped) [0x00000] in :0
    at Xamarin.Forms.Platform.iOS.ListViewRenderer.OnCollectionChanged (System.Object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x00000] in :0
    at Xamarin.Forms.TemplatedItemsList2[Xamarin.Forms.ItemsView1[Xamarin.Forms.Cell],Xamarin.Forms.Cell].OnCollectionChanged (System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x00000] in :0
    at Xamarin.Forms.TemplatedItemsList2[Xamarin.Forms.ItemsView1[Xamarin.Forms.Cell],Xamarin.Forms.Cell].OnProxyCollectionChanged (System.Object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e, Boolean fi
    xWindows) [0x00000] in :0
    at Xamarin.Forms.TemplatedItemsList2[Xamarin.Forms.ItemsView1[Xamarin.Forms.Cell],Xamarin.Forms.Cell].OnProxyCollectionChanged (System.Object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x00000] in :0
    at Xamarin.Forms.ListProxy.OnCollectionChanged (System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x00000] in :0
    at Xamarin.Forms.ListProxy.Clear () [0x00000] in :0
    at Xamarin.Forms.ListProxy.OnCollectionChanged (System.Object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x00000] in :0
    at (wrapper delegate-invoke) :invoke_void__this___object_NotifyCollectionChangedEventArgs (object,System.Collections.Specialized.NotifyCollectionChangedEventArgs)
    at (wrapper delegate-invoke) :invoke_void__this___object_NotifyCollectionChangedEventArgs (object,System.Collections.Specialized.NotifyCollec
    tionChangedEventArgs)
    at System.Collections.ObjectModel.ObservableDictionary2[System.String,System.String].OnCollectionChanged (System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x00000] in <filename unknown>:0 at System.Collections.ObjectModel.ObservableDictionary2[System.String,System.String].OnNotifyRemove (KeyValuePair2 item) [0x00000] in <filename unknown>:0 at System.Collections.ObjectModel.ObservableDictionary2[System.String,System.String].Remove (System.String key) [0x00000] in :0
    at Acr.XamForms.Mobile.AbstractSettings.Remove (System.String key) [0x00014] in c:\dev\acr-xamarin-forms\Acr.XamForms.Mobile\AbstractSettings.cs:84
    at Samples.ViewModels.SettingsViewModel+<>c__DisplayClass3+<b__2>d__9.MoveNext () [0x000d2] in c:\dev\acr-xamarin-forms\Samples\Samples\ViewModels\SettingsViewModel.cs:37

  • Chris.4142Chris.4142 USMember

    @MarkSmith.6714‌ I have tried to use your demo, but keep getting the runtime warning

    "Binding: '' property not found on 'JulMar.Collections.ObservableDictionary`2[System.String,System.Object]', target property: 'Xamarin.Forms.Label.Text'"

    Is there a way to solve this?

  • MarkSmith.8123MarkSmith.8123 USXamarin Team, University, XamUProfessors Xamurai

    Hi @Chris.4142,

    I think this is a minor bug in the binding system, the update does work, the value is being updated and the binding is catching the update, but it appears that it is evaluating the binding twice, and the second time the property path is empty - hence the warning. I'm going to take it up with the Xamarin.Forms team and see what they say.

    Thanks!
    Mark

  • MarkSmith.8123MarkSmith.8123 USXamarin Team, University, XamUProfessors Xamurai

    I have verified that this is fixed in the current 1.3 builds on the Nuget alpha channel, so once it ships to stable you should be good. Thanks!

  • Chris.4142Chris.4142 USMember

    @MarkSmith.6714‌ Thanks so much :) This has helped me a lot!

  • Thank you for your answer But, it doesn't seem to work for a dynamically created control. I am trying for add controls dynamically to a form and then trying to bind this observable dictionary. Please help me in that case. The following is the code:

    IDictionary<string, object> values = new ObservableDictionary<string, object> {
    { "UserName", 10 }
    };
    Content = new Label { };
    Content.SetBinding(Label.TextProperty, "UserName");
    Content.BindingContext = values.Keys;

    This is a code from a view and then I am adding it to the page using the following code in the App.cs file:

    MainPage = new ContentPage { Content = new View1() };

    It doesn't seem to bind the values. Please let me know if you require any further information. Thank you.

  • Thank you. Got it resolved.

  • marceloctorresnmarceloctorresn COMember ✭✭

    Hello!! this is my solution:

            <ListView Grid.Row="3"
                      Margin="5,10,5,10"
                      SeparatorVisibility="Default"
                      SeparatorColor="Gray"
                      ItemsSource="{Binding Path=Grafico.Attributes}">
              <ListView.ItemTemplate>
                <DataTemplate>
                  <ViewCell>
                    <StackLayout Orientation="Vertical"
                                 Spacing="1"
                                 Margin="5"
                                 Padding="2">
                      <Label Text="{Binding Key, StringFormat='{0}:'}"
                             HorizontalOptions="FillAndExpand"
                             VerticalOptions="End"
                             FontAttributes="Bold" />
                      <Label Text="{Binding Value}"
                             HorizontalOptions="FillAndExpand"
                             VerticalOptions="Start"
                             FontAttributes="None" />
                    </StackLayout>
                  </ViewCell>
                </DataTemplate>
              </ListView.ItemTemplate>
            </ListView>
    

    Where Grafico is a property defined in the ViewModel file, and Attributes is the Dictionary

  • IvanositoIvanosito COMember ✭✭

    Hi Marcelo!

    Could you please show me how exactly did you code Grafico and Attributes in the ViewModel?

Sign In or Register to comment.