I'm struggling with control templates. I'm currently building a UI which has several panes which are essentially build out of more basic controls.
here's how one of our construction panes looks like right now:
<Grid>
<StackPanel>
<ContentControl Template="{StaticResource ConstructionBorderCtrl}">
<ContentControl Template="{StaticResource StringCtrl}" Content="Cash Event Value:"/>
</ContentControl>
<ContentControl Template="{StaticResource ConstructionBorderCtrl}">
<ContentControl Template="{StaticResource RateCtrl}"></ContentControl>
</ContentControl>
<ContentControl Template="{StaticResource ConstructionBorderCtrl}">
<ContentControl Grid.Row="0" Template="{StaticResource FromCtrl}"></ContentControl>
</ContentControl>
<ContentControl Template="{StaticResource ConstructionBorderCtrl}">
<ContentControl Grid.Row="0" Template="{StaticResource StartEndDateCtrl}"></ContentControl>
</ContentControl>
<ContentControl Template="{StaticResource ConstructionBorderCtrl}">
<ContentControl Grid.Row="0" Template="{StaticResource ComboStringCtrl}">Applicable Size:</ContentControl>
</ContentControl>
</StackPanel>
</Grid>
Here's a template for the StringCtrl as an example:
<ControlTemplate x:Key="StringCtrl" TargetType="ContentControl">
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Name="ctrlText" Margin="0,0,5,0" Text="{TemplateBinding Content}"></TextBlock>
<TextBox Name="ctrlDefaultValue" Grid.Column="1" />
</Grid>
</ControlTemplate>
As you can see from the template it's really just a label and a textbox. Now let's say I wanted to provide a default value to the text box as well as perform validation on user input, but I want to provide that context from the parent Construction pane and bind it to the individual elements inside the templates. How would I go about doing that?
This is certainly a design I've never seen before. I'd think UserControls or some other type of custom control would work better for this than the ControlTemplate approach.
But if you definitely want to go down this route, I could maybe see a Behavior working for you if there's some consistency to your structure/naming in the templates - you can set properties on the behavior and the behavior can access the control via its AssociatedObject property to be able to set the values of the children and do validation.
Seems like a lot of work to me though.
Related
I have a user control with many sub controls within a grid. Since there are many controls per row, I'm controlling the visibility of the controls by setting the row height of their containing row to 0 (to hide them).
I'm using a validation template on some of these controls and displaying an icon next to the control using AdornedElementPlaceholder.
Since I'm not actually setting the visibility property of the adorned control, but instead hiding the row, the validation icon is not collapsed with the rest of the control.
Here's an abridged version of my XAML code:
<UserControl
<UserControl.Resources>
<ControlTemplate x:Key="ValidationTemplate" TargetType="Control">
<DockPanel>
<Grid
Width="16"
Height="16"
Margin="10,0,0,0"
VerticalAlignment="Center"
DockPanel.Dock="Right">
<Image Source="{x:Static icons:Icons.ValidationIcon}" ToolTip="{Binding Path=ErrorContent}" />
</Grid>
<AdornedElementPlaceholder />
</DockPanel>
</ControlTemplate>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition Height="{Binding Path=ScheduleType, Mode=OneWay, Converter={StaticResource ScheduleTypesToGridRowHeightConverter}, ConverterParameter={x:Static local:ScheduleTypes.Other}}"/>
<RowDefinition Height="{Binding Path=ScheduleType, Mode=OneWay, Converter={StaticResource ScheduleTypesToGridRowHeightConverter}, ConverterParameter={x:Static local:ScheduleTypes.Fixed}}"/>
<RowDefinition Height="{Binding Path=ScheduleType, Mode=OneWay, Converter={StaticResource ScheduleTypesToGridRowHeightConverter}, ConverterParameter={x:Static local:ScheduleTypes.Weekly}}"/>
<RowDefinition Height="{Binding Path=ScheduleType, Mode=OneWay, Converter={StaticResource ScheduleTypesToGridRowHeightConverter}, ConverterParameter={x:Static local:ScheduleTypes.FreeText}}"/>
</Grid.RowDefinitions>
<controls:DateInputBox
Grid.Column="2"
Grid.Row="5"
Height="28"
HorizontalAlignment="Left"
Watermark=""
Width="110"
Text="{Binding StartDateText, ValidatesOnDataErrors=True, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
Validation.ErrorTemplate="{StaticResource ValidationTemplate}"
VerticalAlignment="Center"
ParseComplexDates="True"/>
</Grid>
</UserControl>
From what I understand from a little research is that the validation icon is being displayed in the adorner layer, so doesn't collapse with the rest of the controls.
I'm now thinking that the "row height visibility pattern" was maybe not the best approach ;-) Is there a way I can get this to work without having to completely change my design? I do have a workaround using my view model but I'd like to explore other options first.
If you really whant to stick with the design, you could remove and add the adornents depending of what you whant to display. However, this would be pretty messy and defeat the point of sticking with the current desing for simplicity in the first place.
The concept of hiding elements by setting their parent element size to zero is indeed not the best option. Partly because of the exact issue you mentioned. (The adornents visibility is dependent on its owners visibility. And the owner elements visibility is visible, there is just no space to render it.)
A better option would be to only show whatever is to be shown. An easy way to accomplish this would be to encapsulate all the elements you whant to hide/show together inside one element or user control and then hide or show only that parent element or user control.
This could for instance look like this:
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis" />
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Border Grid.Row="1" Visibility="{Binding FixedIsVisible, Converter={StaticResource BoolToVis}">
<!-- fixed shedule content here -->
</Border>
<Border Grid.Row="1" Visibility="{Binding WeeklyIsVisible, Converter={StaticResource BoolToVis}">
<!-- weekly shedule content here -->
</Border>
<Border Grid.Row="1" Visibility="{Binding FretextIsVisible, Converter={StaticResource BoolToVis}">
<!-- free text shedule content here -->
</Border>
</Grid>
By using some other converter you also yould directly bind you ScheduleType so you dont need to touch your view model.
A maybe even better option would be to make it so that only the elements you need at a time exist inside the view. This could be acomplished by defining different user controls and then have your grid line contain only the desired control at a time. (I might add an example for this later when i have time to do so.)
I've a problem to connect.
I started to connect my tabs with a tabcontrol.ressources and it worked to show the text of each tabs.
Then I wanted to had a scroll for my TabItems and it doesn't work, nothing shows in tab... I can't even use tabcontrol.ressources anymore...
<DockPanel>
<Button Background="DarkGoldenrod" Height="Auto" Command="{Binding OpenFlyoutDataCommand}">
<StackPanel>
<materialDesign:PackIcon Kind="ArrowRightBoldCircleOutline" Width="30" Height="30"/>
</StackPanel>
</Button>
<TabControl ItemsSource="{Binding TabEDCWaferData, Mode=TwoWay}"
SelectedItem="{Binding SelectedTabEDCWaferData}">
<!-- Used to create a scroolbar for tabitems -->
<TabControl.Template>
<ControlTemplate TargetType="TabControl">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Hidden" >
<TabPanel Grid.Column="0" Grid.Row="0"
Margin="2,2,2,0" IsItemsHost="true"/>
</ScrollViewer>
<ContentPresenter ContentSource="..."/>
</Grid>
</ControlTemplate>
</TabControl.Template>
<!-- Contains the text in the tab item ! -->
<TabControl.Resources>
<DataTemplate DataType="TabItem">
<DockPanel>
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=Content}" />
</DockPanel>
</DataTemplate>
</TabControl.Resources>
</TabControl>
</DockPanel>
This is connected to a collection of TabItem, where I've a function to add Items binding to an other button.
private ObservableCollection<TabItem> _TabEDCWaferData;
public ObservableCollection<TabItem> TabEDCWaferData
{
get { return _TabEDCWaferData; }
set
{
_TabEDCWaferData = value;
RaisePropertyChanged("TabEDCWaferData");
}
}
public void AddTabItem(string name)
{
TabItem tab = new TabItem();
tab.Header = name;
tab.Content = "Temporary content";
TabEDCWaferData.Add(tab);
}
I read that I have to use the ContentPresenter, but I don't know how to bind it. I think this is not working with TabItems...
I just want to bind it as I did in the Ressources by using the ContentPresenter.
I hope that I'm clear enough ! Thanks
EDIT : I try to display in the ContentPresenter the selected item tab content that I add in the function `AddTabItem.
With ContentPresenter, most times, this does the job:
<ContentPresenter />
The default ContentSource is "Content". That means it'll look at the Content property of the templated parent and it'll take whatever it finds there for its own content.
But that doesn't help you at all, and you don't have to use ContentPresenter; it's just a convenience. In this case, the content you want to present is SelectedItem.Content, which isn't a valid ContentSource for ContentPresenter. But you can do the same thing with a binding on a ContentControl instead:
<TabControl.Template>
<ControlTemplate TargetType="TabControl">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<ScrollViewer
Grid.Row="0"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Hidden"
>
<TabPanel
Grid.Column="0"
Margin="2,2,2,0" IsItemsHost="true"/>
</ScrollViewer>
<ContentControl
Grid.Row="1"
Content="{Binding SelectedItem.Content, RelativeSource={RelativeSource TemplatedParent}}"
/>
</Grid>
</ControlTemplate>
</TabControl.Template>
TemplateBinding isn't going to work with a Path such as "SelectedItem.Content"; it only accepts names of properties on the templated parent. I fixed your Grid.Row attributes, too.
Also, you may as well delete that DataTemplate for TabItem that you put in TabControl.Resources. That's not what DataTemplate is for; you use DataTemplates to define visual presentations for your viewmodel classes, but TabItem is a control. It already knows how to display itself, and in fact that DataTemplate is being ignored, so it's best not to leave it there; you'll only waste time later on making changes to it and trying to figure out why it's not having any effect. Your TabItems will display correctly without it.
Try something like this ?
<ContentPresenter Content="{TemplateBinding Content}" />
Edit
<ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" />
I'm writing a UWP app to track TV shows watched/purchased/streamed etc and
am going absolutely crazy trying to get grid columns inside a DataTempate to stretch their width as it seems there is a bug in XAML which ignores the * width definition. I need the first column in the ListView (the show Title) to take up the remaining space (hence the column definition = "*") and while it will do that in the HeaderTemplate it absolutely refuses to do it inside the DataTemplate so the whole grid just ends up being all wonky and out of alignment as the Title column only uses the space it needs on each line.
My XAML is below - in the ItemTemplate DataTemplate template I am binding to an instance of an object called TVShow which is in an observable collection in my main view model. (I have not included the ViewModel or TVShow class definition here as I know this is a purely XAML issue).
The only thing that worked so far is having an extra property in my TVShow class that stores the correct width of the column (by subtracting the widths of the other three columns from the grid size (fetched in the view code behind) but this causes the whole list to reformat itself after initally displaying which looks ugly, not to mention awful programming.
So I'm looking for ideas on how to solve this - I could move the property for the correct column width in the main viewmodel but then how do I bind to that in the template given I am binding to "TVShow"? Or do I have to take the content out of the DataTemplate and put in a UserControl? I have wasted so much time on something that is so ridiculously simple - this bug seems to have been around since WPF so why haven't MS ever fixed this - very frustrating.
<HubSection Name="hsShows" Width="{Binding HubSectionWidth}" MinWidth="430" MaxWidth="640"
VerticalAlignment="Top" HorizontalAlignment="Stretch" Background="{StaticResource Dark}" >
<HubSection.Header>
<TextBlock Text="Shows" TextLineBounds="TrimToBaseline" OpticalMarginAlignment="TrimSideBearings"
FontSize="24" Foreground="{StaticResource Light}"/>
</HubSection.Header>
<DataTemplate x:DataType="local:MainPage">
<ListView Name="lvwShows"
Width="{Binding HubSectionGridWidth}"
Grid.Row="0"
Foreground="{StaticResource Light}"
Background="{StaticResource Dark}"
Margin="-14,20,0,0"
Loaded="lvwShows_Loaded"
ItemsSource="{Binding AllShows}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
IsSwipeEnabled="True"
IsItemClickEnabled="True"
SelectedItem="{Binding SelectedTVShow, Mode=TwoWay}"
SelectionMode="Single"
ScrollViewer.VerticalScrollMode="Enabled"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.HeaderTemplate>
<DataTemplate>
<Grid Width="{Binding HubSectionGridWidth}" Height="Auto" Background="DarkGreen" Margin="15,5,5,5" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="80"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Title" FontSize="16" FontWeight="Bold" Foreground="{StaticResource Bright}"
VerticalAlignment="Bottom" HorizontalAlignment="Left"
Tag="TITLE,ASC" Tapped="ShowsGridHeading_Tapped"/>
<TextBlock Grid.Column="1" Text="Seasons" FontSize="16" FontWeight="Bold" Foreground="{StaticResource Bright}"
VerticalAlignment="Bottom" HorizontalAlignment="Center"
Tag="SEASONS,ASC" Tapped="ShowsGridHeading_Tapped"/>
<TextBlock Grid.Column="2" Text="Last Watched" FontSize="16" FontWeight="Bold" Foreground="{StaticResource Bright}"
VerticalAlignment="Bottom" HorizontalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap"
Tag="WATCHED,ASC" Tapped="ShowsGridHeading_Tapped"/>
<TextBlock Grid.Column="3" Text="Last Episode" FontSize="16" FontWeight="Bold" Foreground="{StaticResource Bright}"
VerticalAlignment="Bottom" HorizontalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap"
Tag="EPISODE,ASC" Tapped="ShowsGridHeading_Tapped"/>
</Grid>
</DataTemplate>
</ListView.HeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate x:DataType="model:TVShow">
<Grid Height="Auto" MinWidth="410" MaxWidth="640" Background="Blue" HorizontalAlignment="Stretch" RightTapped="ShowsList_RightTapped">
<FlyoutBase.AttachedFlyout>
<MenuFlyout Placement="Bottom">
<MenuFlyoutItem x:Name="UpdateButton" Text="Update from TVMaze" Click="FlyoutUpdateButton_Click"/>
<MenuFlyoutItem x:Name="RefreshButton" Text="Refresh" Click="FlyoutRefreshButton_Click"/>
<MenuFlyoutItem x:Name="DeleteButton" Text="Delete Show" Click="FlyoutDeleteButton_Click"/>
</MenuFlyout>
</FlyoutBase.AttachedFlyout>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="80"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="{x:Bind Title}" Foreground="{StaticResource Light}"
VerticalAlignment="Center" HorizontalAlignment="Stretch" TextWrapping="Wrap" />
<TextBlock Grid.Row="0" Grid.Column="1" Text="{x:Bind Seasons}" Foreground="{StaticResource Light}"
VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock Grid.Row="0" Grid.Column="2" Foreground="{StaticResource Light}"
Text="{x:Bind LastWatchedDate, Mode=OneWay, Converter={StaticResource DateTimeFormatConverter}, ConverterParameter='{}{0:dd/MM/yyy HH\\\\:mm}'}"
VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock Grid.Row="0" Grid.Column="3" Text="{Binding LastWatchedEpisodeRef}" Foreground="{StaticResource Light}"
VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</DataTemplate>
</HubSection>
Ok, so I ended up adding this XAML into my ListViews (though I know I could have done what Grace suggested but I just find Blend horrific to use) - it was the HorizontalContentAlignment that actually did the trick!
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
If you have Correct width in viewmodel you can Bind it like this
Width={Binding ElementName = ListViewname,Path=DataContext.width}
This problem is caused by the default template of the ListViewItem, to make the Grid stretch inside of the items, you can open the Document Outline label => find your ListView control and right click on it, then choose Edit Additional Templates => select Edit Generated Item Container (ItemContainerStyle), and at last Edit a Copy.
Then you will find this template in your Page resources, please change the code:
<Setter Property="HorizontalContentAlignment" Value="Left" />
To:
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
Then your problem can be solved.
I saw you've more then one ListView, if you want this style target all the ListView in this page, you can remove the x:Key attribute of this template and remove the ItemContainerStyle with the StaticResource which is generated by the action upper.
Don't be frustrating, I think you have developed WPF before, it's easy to learn UWP. Editing the template or the styles of the controls can solve many layout problem, here is some default templates and styles of different controls, you may take a look next time you have such problem.
If you have questions about how to develop an UWP app, you can refer to Develop UWP apps, and if you have some problems with the APIs, you may refer to Reference for Universal Windows apps.
If you need help or suggestion, you may ask question here, people here are glad to help.
I've been trying to create a custom menu. For this reason I wanted to use an ItemsControl in order to make it flexible. After hours of headache I figured out how to make it - kinda.
I have my custom ItemsControl "LiftMenu" (which is not yet much custom but standard) and an UserControl called "LiftItem". Last but not least I got the Model-class "LiftMenuItem".
By adding a new LiftMenuItem to the LiftMenu, it should display a new LiftItem-control as corresponding item. So far so good, I managed to get this working.
In that LiftItem-control I bind like I would in a normal DataTemplate: plain bindings with a path, nothing more. Normally this would work just fine because the DataTemplate already has it's context set to the model-type.
But now I just get an empty control that does nothing and shows nothing, because the bindings don't work.
I implemented it this way:
<menu:LiftMenu HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MinHeight="200" Background="#80A8A8A8" Margin="5,0,0,0">
<menu:LiftMenu.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</menu:LiftMenu.ItemsPanel>
<menu:LiftMenu.ItemTemplate>
<DataTemplate DataType="{x:Type menu:LiftMenuItem}">
<menu:LiftItem />
</DataTemplate>
</menu:LiftMenu.ItemTemplate>
<menu:LiftMenuItem Header="Test1"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Border x:Name="border" BorderBrush="{Binding LabelColor}" BorderThickness="1" HorizontalAlignment="Left" Height="Auto" Margin="0"
VerticalAlignment="Stretch" Width="4" Background="{Binding BorderBrush, ElementName=border}"/>
<TextBlock Text="{Binding Header}" TextTrimming="CharacterEllipsis" Margin="5,0,5,0" HorizontalAlignment="Left" VerticalAlignment="Center"
Foreground="White" />
<controls:ProgressRing x:Name="ring" Grid.Column="2" HorizontalAlignment="Right" Stroke="#ffff8000" VerticalAlignment="Center"
Minimum="0" Maximum="100" Value="{Binding ProcessValue}" IsIndeterminate="{Binding ProcessIndeterminate}" Visibility="{Binding ProcessVisibility}"
Width="20" Height="20" Radius="10" Margin="2,0,2,0" />
</Grid>
In the end there is no text, no border. Just the ProgressRing is visible.
How can I fix this? This ListItem-control should become similiar to a button, thus I need to do some styling (animation, ...). I can't do this within a normal DataTemplate, but I don't want to miss the binding features of WPF on that. This would make it relatively unflexible.
What's the problem? I probably just miss some DataContext or so, but I don't know what it would be.
I am using a DataTemplateSelector to select different UserControls (reference http://tech.pro/tutorial/807/wpf-tutorial-how-to-use-a-datatemplateselector), according the selected path I select the needed UserControl.
The problem is now, when using the WebBrowser Control, I should bind it to ActualHight of MyScrollViewer, but on all others it works with Hight or else the scroll bar is displayed bad. Must come from the WebBrowser control.
How can I switch the Bindings in the ContentControl between Hight/ActualHight depending of the loaded UserControl?
<DataTemplate x:Key="WebTemplate1">
<DockPanel LastChildFill="True">
<controls:WebBrowserUserControl SourceHtml="{Binding Converter={StaticResource UriConverter1}}" />
</DockPanel>
</DataTemplate>
<DataTemplate x:Key="ImgTemplate1">
<Image Source="{Binding Converter={StaticResource RelativeToAbsolutePathConverter1}}"
Stretch="None" />
</DataTemplate>
...
<ScrollViewer Name="MyScrollViewer"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
DockPanel.Dock="Left"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<Grid x:Name="MyGridHelper">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<DockPanel x:Name="MyDockPanel" Dock="Top" HorizontalAlignment="Left">
<ContentControl x:Name="MyContentControl"
Width="{Binding ElementName=MyScrollViewer,
Path=Width/ActualWidth}"
Height="{Binding ElementName=MyScrollViewer,
Path=Height/ActualHight}"
Content="{Binding Path=CurrentItem1,
Mode=OneWay}"
ContentTemplateSelector="{StaticResource MyTemplateSelector}" />
</DockPanel>
</Grid>
</ScrollViewer>
The DataTemplateSelector by itself cannot affect the other properties of the ContentControl, however, you could use a Converter to determine the Width\Height based on the same logic used to determine which template to use. So something like this:
<ContentControl x:Name="MyContentControl"
Width="{Binding ElementName=MyScrollViewer, Converter={StaticResource MyWidthConverter}, ConverterParameter="???"}"
Height="{Binding ElementName=MyScrollViewer, Converter={StaticResource MyHeightConverter}, ConverterParameter="???"}"
Content="{Binding Path=CurrentItem1, Mode=OneWay}"
ContentTemplateSelector="{StaticResource MyTemplateSelector}" />
I put question marks for the ConverterParameter because I'm not clear on how you determine which case calls for which Width/Height. But you can pass in a parameter that will allow you to decide which value to pass back, and based on that decision, the Converter can determine whether to get the ActualWidth/ActualHeight or the Width/Height of the ScrollViewer that is passed in.