Binding to an element of a Window ancestor - wpf

In this code I correctly print the Window Title in the label
<Window x:Class="Crono4.Views.MainWindow"
...>
<DockPanel>
<Grid ...>
<RadioButton x:Name="buttonProduct" Content="Product"/>
<RadioButton .../>
</Grid>
<Grid>
<Label x:Name="label" Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=Title}"/>
</Grid>
</DockPanel>
</Window>
But if I want to refer to the name of the button, this doesn't work:
<Label x:Name="label" Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=buttonProduct.Content}"/>
Why?
Thanks,

Because buttonProduct is not a property of the window and you can only bind to public properties.
You could try using an ElementName to bind to the RadioButton:
<Label x:Name="label" Content="{Binding ElementName=buttonProduct, Path=Content}"/>

Related

I'm looking for a code snippet describing how to code a complex wpf ItemsTemplate

I'm displaying a list with formatted text and graphics. the code works but the second StackPanel is not displaying the the Entity.LabelWdth object on the right side of the screen. That is the Horizontal Orientation is not working. I do not know how to code the proper template (code snippet for mixed panel layouts).
<ListBox ItemsSource="{Binding Entity.LowerCanvases}" MouseLeftButtonUp="LowerCanvas_MouseLeftButtonUp">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="-7,10,0,0" Orientation="Vertical">
<Canvas Width="{Binding Entity.ScrWth, RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type UserControl}}}" Height="{Binding Entity.LowerDrawHght,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}">
<StackPanel Orientation="Horizontal">
<ContentControl Content="{Binding LowerDrawing}" />
<ContentControl Content="{Binding LowerLabel}" />
</StackPanel>
</Canvas>
<Canvas Width="{Binding Entity.ScrWth}" Height="30">
<ContentControl Content="{Binding LowerFooter}" />
</Canvas>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>
I found a solution. The content controls were also a collection of canvases, so
I had to position the content controls with canvas Left and Top attached property.
<ListBox ItemsSource="{Binding Entity.LowerCanvases}" MouseLeftButtonUp="LowerCanvas_MouseLeftButtonUp">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Canvas Margin="-7,10,0,0"
Width="{Binding Entity.ScrWth, RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type UserControl}}}" Height="{Binding Entity.LowerDrawHght,
RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}">
<!-- These two control should be on the same line -->
<ContentControl Content="{Binding LowerDrawing}" Canvas.Left="0" />
<ContentControl Content="{Binding LowerLabel}" Canvas.Left="{Binding Entity.DrawingWth,
RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"/>
<!-- THis control should be on the following line -->
<ContentControl Content="{Binding LowerFooter}" Canvas.Top= "{Binding Entity.LowerDrawHght,
RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"/>
<!--<TextBlock>
<Run Text="{Binding Entity.DrawingWth, StringFormat='{}{0:#,0}',
RelativeSource={RelativeSource FindAncestor,
AncestorType=UserControl}}" FontSize="22"/>
</TextBlock>-->
</Canvas>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>

Binding to the Title of a Window does not always work

I need to databind two TextBlocks to the Window.Title property. The first one works via:
RelativeSource FindAncestor, AncestorType=Window}"
But the second one does not (it's deeply nested within a button ToolTip).
How can I change the second one to make it also display the Title of the Window?
<Window ...>
<Border ...>
<Grid ...>
<Grid ...>
<!-- TEXTBLOCK BELOW WORKS -->
<TextBlock Grid.Column="2" Text="{Binding Title, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
HorizontalAlignment="Stretch" VerticalAlignment="Center" Foreground="White" FontSize="18px" FontStretch="UltraExpanded" />
<Button Grid.Column="3" HorizontalAlignment="Right" VerticalAlignment="Stretch"
Background="Transparent" BorderBrush="Transparent" Foreground="Transparent"
ToolTipService.InitialShowDelay="0" ToolTipService.BetweenShowDelay="0" ToolTipService.ShowDuration="60000">
<Button.ToolTip>
<ToolTip x:Name="helpButtonTooltip" Width="240" ToolTipService.InitialShowDelay="0">
<!-- TEXTBLOCK BELOW DOES NOT WORK; HOW CAN I MAKE IT WORK? -->
<TextBlock Text="{Binding Title, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
HorizontalAlignment="Stretch" VerticalAlignment="Center" Foreground="White" FontSize="18px" FontStretch="UltraExpanded" />
The tool tip is displayed in a popup and is not part of the same visual tree as the button or your window. Consequently, RelativeSource and ElementName bindings do not work.
What you can do is bind the window title to the Tag property of your button and then bind the Text of the tool tip TextBlock to the Tag property of the PlacementTarget (which is the button).
<Button Tag="{Binding Title, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}">
<Button.ToolTip>
<ToolTip>
<TextBlock Text="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource AncestorType={x:Type ToolTip}}}"/>
</ToolTip>
</Button.ToolTip>
</Button>

Is there a way to define more than one itemtemplate in the default treeview?

Or is my only option to extend the original treeview if I want that capability?
I want something like this, but with the two itemspresenters having two different templates defined so that they both use the same items, but apply a different template to create controls in those two spots.
<ControlTemplate>
<Grid>
<wpfExp:SignalNameBox x:Name="TreeViewTimeTextBox" Grid.Row="0" Grid.Column="0"
Height="{Binding RelativeSource = {RelativeSource AncestorType={x:Type wpfExp:GraphViewer}}, Path=GraphHeight}"
Width="200"
Margin="19,0,0,0"
MainText="Time"
/>
<wpfExp:SignalGraphAxis
x:Name="signal_axis"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
GraphHeight="{Binding RelativeSource = {RelativeSource AncestorType={x:Type wpfExp:GraphViewer}}, Path=GraphHeight}"
MinWidth="10"
MinHeight="10"
PenColor="{Binding ElementName=AxisColorPicker, Path=SelectedColor, Mode=OneWay}"
PenWidth="{Binding RelativeSource = {RelativeSource AncestorType={x:Type wpfExp:GraphViewer}}, Path=GraphPenWidth, Mode=OneWay}"
MaxTimeValue="{Binding RelativeSource = {RelativeSource AncestorType={x:Type wpfExp:GraphViewer}}, Path=_SignalDataViewModel.MaxTimeValue}"
TimeUnit="{Binding RelativeSource = {RelativeSource AncestorType={x:Type wpfExp:GraphViewer}}, Path = TimeUnit}"
AxisDivisionUnit="{Binding RelativeSource = {RelativeSource AncestorType={x:Type wpfExp:GraphViewer}}, Path = AxisDivisionUnit}"
/>
<StackPanel>
<ItemsPresenter/>
</StackPanel>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<StackPanel>
<ItemsPresenter/>
</StackPanel>
</ScrollViewer>
</Grid>
</ControlTemplate>
A simplest example I am taking here is to show Contacts with different background color based on their sex(Male/Female).
So this is how the ItemTemplateSelector class will look
class MyDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item != null)
{
Contact objContact = item as Contact ;
switch (objContact.Sex)
{
case "Male": return App.Current.MainWindow.FindResource("TemplateMale") as DataTemplate;
case "Female": return App.Current.MainWindow.FindResource("TemplateFemale") as DataTemplate;
}
}
return null;
}
}
and this is how you can use it in your XAML
<Window.Resources>
<local:MyDataTemplateSelector x:Key="myTemplateSelector"></local:MyDataTemplateSelector>
<DataTemplate x:Key="TemplateMale">
<TextBlock Background="Blue" Text="{Binding Name}"></TextBlock>
</DataTemplate>
<DataTemplate x:Key="TemplateFemale">
<TextBlock Background="Pink" Text="{Binding Name}"></TextBlock>
</DataTemplate>
</Window.Resources>
<TreeView ItemsSource="{Binding Contacts}"
ItemTemplateSelector="{StaticResource myTemplateSelector}">
</TreeView>

Bind to other element in a stackpanel without name

I'm creating a DataTemplate in WPF, so it won't compile if I use x:Name. This is the relevant part of my code:
<DataTemplate>
<StackPanel>
<Image .../>
<Textbox Width={Binding to image?, Path=ActualWidth} />
</StackPanel>
</DataTemplate>
How can I bind to the Image without the use of name?
You can use RelativeSource:
<DataTemplate>
<StackPanel>
<Image Source="{Binding Photo}"/>
<TextBox Width="{Binding Path=Children[0].ActualWidth, Mode=OneWay, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=StackPanel, AncestorLevel=1}}" />
</StackPanel>
</DataTemplate>
You can't directly binding to Image but you can do that with StackPanel and property Children.

How to bind a property of ViewModel to an element in HierarchicalDataTemplate of a Treeview?

How to bind a property of ViewModel to an element in HierarchicalDataTemplate of a Treeview (the property is is out of HierarchicalDataTemplate.Itemsource)
this is the example and the probelm is in this line: Visibility="{Binding IsCheckBoxVisible , RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}, Converter={StaticResource debuger}}"/>
<UserControl ....>
<Grid>
<TreeView ItemsSource="{Binding Roots}" Grid.Row="0">
<TreeView.ItemContainerStyle>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate >
<HierarchicalDataTemplate ItemsSource="{Binding ConfigedChildren}">
<StackPanel Orientation="Horizontal" >
<CheckBox IsChecked="{Binding IsChecked}" Visibility="{Binding IsCheckBoxVisible, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}, Converter={StaticResource debuger}}"/>
<Label Content="{Binding Title}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
<CheckBox IsChecked="{Binding IsChecked}" Visibility="{Binding DataContext.IsCheckBoxVisible, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}, Converter={StaticResource debuger}}"/>
Use DataContext.IsCheckBoxVisible. Hope this will work

Resources