简体   繁体   中英

Can I bind the Height of a XAML Grid back to my C# back end code?

I have some XAML code that looks like this. It names four grids and then in the back end my C# does something based on the values. As I can not have duplicate names I created four names.

But I would like to simplify the back-end code so is it possible that I could bind back the value of the height from my XAML > ViewModel and then check that value in my C#

<Grid IsVisible="{Binding AVisible}" VerticalOptions="FillAndExpand">
   <Grid x:Name="aWords" VerticalOptions="FillAndExpand" >
      <Frame VerticalOptions="FillAndExpand">
         <Frame.Content>
            <Grid x:Name="aArea" VerticalOptions="CenterAndExpand">
               <Label Text="{Binding Detail}"
            </Grid>
         </Frame.Content>
      </Frame>
   </Grid>
</Grid>
<Grid IsVisible="{Binding BVisible}" VerticalOptions="FillAndExpand">
   <Grid x:Name="bWords" VerticalOptions="FillAndExpand" >
      <Frame VerticalOptions="FillAndExpand">
         <Frame.Content>
            <Grid x:Name="bArea" VerticalOptions="CenterAndExpand">
               <Label Text="{Binding Detail}"
            </Grid>
         </Frame.Content>
      </Frame>
   </Grid>
</Grid>

and in C#

var a = aWords.Height;
var b = aArea.Height;
if (b > a) doSomething();

var c = aWords.Height;
var d = aArea.Height;
if (d > c) doSomething();

What I would like to do is like this:

if (vm.AreaHeight > vm.WordsHeight) doSomething();

The way you can pass those values to your ViewModel is by using the binding context of your page for interacting with the ViewModel methods and properties.

First, create a couple of properties in your ViewModel to hold the Height of your objects: ie:

public int AreaHeight { get; set; }
public int WordsHeight { get; set; }

Then, on your page override the event: OnAppearing() in order to get the Height from your grids using the x:Name attribute, then you will call from your ViewModel the method: doSomething() passing the obtained values as parameters. ie:

    protected override void OnAppearing()
    {
        base.OnAppearing();
        // Get your height from your grids here ...
        // int gridAHeight = aWords.Height;
        // int gridBHeight = aArea.Height;
        (BindingContext as YourViewModel).doSomething(gridAHeight, gridBHeight);
    }

Finally, in your ViewModel, implement the method doSomething() and catch the parameters obtained from the view page by assigning them to your previously created properties. ie:

public void DoSomething(int gridAHeight, int gridBHeight)
{
    AreaHeight = gridAHeight;
    WordsHeight = gridBHeight;
    if (AreaHeight < WordsHeight)
    {
       // place your logic here...
    }
}

That is all you need. It is just basic MVVM pattern .

Passing heights or binding heights to a ViewModel violates MVVM pattern. ViewModels shouldn't know anything about a specific view.

I would suggest refactoring your view and finding a different layout depending on the specifics needed for the page. A possible solution would be to use a ListView with labels and restricting the content in the ObservableCollection so you don't have duplicates.

If you have to have it set up that way, I would suggest using MaxLines and/or LineBreakMode to restrict the height of your Labels.

Issues with doing logic based on height:

  1. FontSize could be different based on AccessibilitySettings specified in the users phone
  2. Rotating the screen will change how much of the label is wrapped due to the label expanding . This would force you to do a recalculation again.

Basically, you can't. There isn't the height in XAML, but rather HeightRequest . The layout is a complex thing and the height may not end up being what is your HeightRequest , it is just a suggested value. So you can only change that suggested value from the view model that is not the problem, but that is not what you asked for.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM