2

I can't get databinding to work within a DataTemplate in Xamarin forms. I can get it to work with the ListView (i.e. binding the RowHeight), but once in the DataTemplate, setting things to a property of my ViewModel has no affect.

In the below example, if I set the ColumnDefinition.Width to a property, it is completely ignored, but setting it to a hard value works fine. I have put in a label to see what the property value is and it turns out blank when inside the Datatemplate, and I have re-checked that the property is correct because if I take the label out of the Listview, it displays the correct value.

Any ideas?

UPDATE:

My Class is "ParentPage" which has 2 properties: "Patients" and "Settings". Patients has an observable collection of "PatientList", How would I bind to the "Settings.Fontsize" shown below in the label. I have tried every combination I can think of:

<ListView   x:Name="listView" ItemsSource="{Binding ParentPage.Patients.PatientsList}" RowHeight="{Binding ParentPage.Settings.RowHeight}"  >
  <ListView.ItemTemplate>
    <DataTemplate>
      <ViewCell>
        <Grid HorizontalOptions="FillAndExpand">
          <Grid.RowDefinitions>
            <RowDefinition Height="*" />
          </Grid.RowDefinitions>
          <Image  Grid.Row="0" Grid.Column="0"
             Source="{Binding Picture}" />

          <Label  TextColor="Red" Text="{Binding ParentPage.Settings.FontSize}"   
       HorizontalOptions="Center" />

        </Grid>     
      </ViewCell>
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>
Cfun
  • 8,442
  • 4
  • 30
  • 62
user197505
  • 163
  • 3
  • 13
  • when you're in a DataTemplate for a List, you are binding to properties that are relative to the List contents - ie, in your case you are binding to an individual Patient and it's properties. Unless each Patient has a Property called ParentPage what you're trying to do won't work. – Jason Oct 17 '16 at 14:15

1 Answers1

9

BindingContext, in other words "ItemsSource" for listview, is appliying to whole listview, include DataTemplate. So, if you wanna bind something, then it property should be in BindingContext, in your case it is Patients. So, Pasient class should include this property. But, there is a trick. Where you want bind something, that is not in listview binding context, then you should name your listview, like x:Name = "YourListView" and then in your datatemplate for your binding write this:

Property="{Binding Source={x:Reference Name = "YourListView"},
          Path=BindingContext.YourNameOfPropertyInViewModel}"

With this, your property will use binding context of your listview element level, that is ViewModel in your case.

Yura Babiy
  • 515
  • 7
  • 22
  • Thanks, that is getting me on the right track but I'm still confused on how to reference the model. – user197505 Oct 17 '16 at 15:40
  • In this example, my parent page has 2 properties, ParentPage.Patients.Patients which is the list items source, and ParentPage.Settings.RowHeight which contains the desired height of the rows. So to access the row height, I have tried things like – user197505 Oct 17 '16 at 15:43
  • I can't understand why you have two times Patients, but what I can say you, that you have two variants, one - add property height to your last Patients, and binding it like you always do, just write heightrequest = "{Binding Height}" or two - say you have viewmodel - ParentPageViewModel, then u must do like i suggested, where path is : BindingContext.RowHeight. Much info is in internet, so just google and read, or provide more specific details, like your viewmodel, view.. – Yura Babiy Oct 17 '16 at 16:03
  • I have 2 patients because the property of my model is "Patients" and the observable collection on that property was also "Patients" which is confusing so I renamed it to "PatientsList". I can't add code here so I will add it as an answer. – user197505 Oct 17 '16 at 19:31
  • You put me on the right track for sure, I finally resigned myself that I had to have the property on the Patients class. I was trying to work around that but don't see it happening. Too bad you can't bind things like that to other sources because font size, etc. doesn't make sense to be in your class (Patients in my case). – user197505 Oct 18 '16 at 12:27
  • I think you not properly think about your mvvm.(I am new in it, so maybe It is I am wrong), but, this trick with x:reference is for don't add property to not relayted model, in your case if heigth is the same for all rows, then you don't need to add it to every model(row). But what it must be in your case, that you should have Patients as list itself, where every item of list is your model. And with it, you will add height property to your viewmodel, and bind it with x:reference. I can send my code, that will be example for you, but I need your email. – Yura Babiy Oct 18 '16 at 12:38