0

I have a "Details View" that needs to be shared among other views.

An example of a view that uses the "Details View"

This code is in a UserControl ParentView.xaml

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*" Name="detailsRowDefinition"/>
    </Grid.RowDefinitions>
    <StackPanel Grid.Row="0"...>
    <StackPanel Grid.Row=1 HorizontalAlignment="Center">
        <!--This is what I'd like to get ActualHeight from-->
        <!--I've tried to get ActualHeight from the RowDefinition as well-->
        <ContentControl Name="detailsView" Content="{Binding Details}"/>
    </StackPanel>
</Grid>

Then another xaml file make sure that the {Binding Details} in the ContentControl above work correctly, and it renders my DetailsView correctly.

Now, in another file DetailsView.xaml (also a UserControl)

<TabControl>
    <TabItem Header="Part A">
        <!--This is the blasted ScrollViewer that I can't set the height on-->
        <ScrollViewer Height="{Binding Path=ActualHeight, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=RowDefinition}}" >
            <!--Lots of crap-->
        </ScrollViewer>
    </TabItem>
    <TabItem Header="Part B">
    </TabItem>
    <!--etc-->
<TabControl>

I've tried different variations of binding like ElementName and setting AncestorLevel really high, etc.

The answer I'm going for is like this one: How to make scrollviewer work with Height set to Auto in WPF? Except that I need to bind to the parent element of the UserControl that this UserControl is embedded in

The answer on this question seems like what I'm trying to do, but there's no help in terms of code snippets.How can I get the actual grid row height of a grid with RowDefinition Height *

Community
  • 1
  • 1
C. Tewalt
  • 2,271
  • 2
  • 30
  • 49
  • One work-around is to create a height `DependencyProperty` in `DetailsView`, and bind the `ScrollViewer` height to it, and then bind the height property of the `Details` object in `ParentView` to the `RowDefinition` height. – Aly Elhaddad Feb 14 '16 at 09:44
  • @AlyEl-Haddad. Where does the DependencyProperty go? Just wrapped around the ScrollViewer? – C. Tewalt Feb 14 '16 at 10:02
  • Do I set that in the CodeBehind? And then when binding from the ParentView, do I use a register attached method? Looking at this link here... https://msdn.microsoft.com/en-us/library/system.windows.dependencyproperty(v=vs.110).aspx – C. Tewalt Feb 14 '16 at 10:08
  • Yes, the property is defined in the code-behind DetailsView, and the binding in ParentView is set like that `Binding b = new Binding() {RelativeSource = //...}; Details.SetBinding(DetailsView.MyHeightProperty, b);` – Aly Elhaddad Feb 14 '16 at 10:24
  • OK. I'm looking at the tutorial here: http://www.wpftutorial.net/DependencyProperties.html – C. Tewalt Feb 14 '16 at 16:20
  • Sorry this does not answer the question you asked. But is this binding really necessary? Wouldn't the `TabControl` vertically stretch itself so that its `ContentPanel`(where the `ScrollViewer` exists) also expand all available vertical spaces? – Peter Feb 14 '16 at 16:21
  • @Peter what I'm seeing currently is that say my MainWindow is 500px high. My Tab Item for Part A has probably 600px high worth of stuff. Then the whole tab control renders 600px high and the information is cut off. – C. Tewalt Feb 14 '16 at 16:24
  • @matrixugly In that case, would it be better by putting the TabControl inside a ScrollViewer? – Peter Feb 14 '16 at 16:44
  • @Peter yeah, I had thought of that... but. I would like the user to be able to change tabs even while the page is scrolled down. – C. Tewalt Feb 14 '16 at 20:21
  • @matrixugly Thanks! Now I understand your intention. As to your question, I would try to bind to `ActualHeight` of the parent `StackPanel` in `ParentView.xaml` since in visual tree `RowDefinition`s are actually siblings of a Grid's children objects so `FindAncestor` can't find them. Or perhaps do not bind but setting ScrollViewer.MinHeight? – Peter Feb 14 '16 at 20:32

2 Answers2

1

RowDefinition does not act as containing contol, so you can't find it as an ancestor. But you don't really need it, you can take the parent Panel (which is StackPanel in your case):

<TabItem Header="Part A">
    <ScrollViewer Height="{Binding ActualHeight, RelativeSource={RelativeSource FindAncestor, AncestorType=StackPanel}}">
        <TextBlock Text="Here we are" />
    </ScrollViewer>
</TabItem>
icebat
  • 4,696
  • 4
  • 22
  • 36
  • You know, I actually just tried this yesterday, and this works. But if you increase the size of your window until the scroll bar disappears, then shrink the window, the scrollbar doesn't come back... It's like the 'ActualHeight' property increases on the stack panel, but doesn't decrease when you shrink it. I need to find the correct element whose 'ActualHeight' property decreases. – C. Tewalt Feb 15 '16 at 14:58
  • I give it a +1 anyway, because I think this is the right approach. – C. Tewalt Feb 15 '16 at 14:59
  • @matrixugly, you can try to replace StackPanel with Grid and set it's HorizontalAlignment and VerticalAlignment to Stretch, maybe that will work more correctly with sizing. But I can't verify you scenario today, will try tomorrow. – icebat Feb 15 '16 at 16:01
  • Yeah... that's a good idea! Instead of trying to shoehorn StackPanel for what I need, I should use a control that has the right sizing behavior I need. I will keep my dumb Event handler, for now, but if the Grid idea works, I'll refactor it and accept your answer :) – C. Tewalt Feb 15 '16 at 16:10
0

For the sake of time, I settled for having an event handler for SizeChanged like this <UserControl SizeChanged="Control_SizeChanged"> element of the Parent.xaml

    private void Control_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        if (e.HeightChanged)
        {
            var height = this.detailsRowDefinition.ActualHeight;
            this.detailsView.Height = height;
        }
    }
C. Tewalt
  • 2,271
  • 2
  • 30
  • 49