Binding to the Title of a Window does not always work - wpf

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>

Related

Binding to an element of a Window ancestor

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}"/>

How to bind to property of sibling control?

In a listbox of items, one item can be designated as the primary item. In the template, I have a button bound to a parameterized command (the specific item in the collection is the parameter passed to the command in the datacontext) that is visible only if the item is not currently the primary item. If the item IS the primary item, I want to display a static image. Since I can't bind the image to the command to witch I am binding the button, I figured I could bind the Visibility property of the image to the "inverse" of the Visibility property of the button. (i.e. when the button is visible, the image is hidden and vice versa.) But I can't figure out how to do this. The button is a sibling of the image within a grid within the template. Here's my template...
<DataTemplate>
<StackPanel Orientation="Vertical">
<Grid>
<Grid.ColumnDefinitions>
...
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Path=FormattedNumber}" Style="{StaticResource FieldDataTextBlock}" FontWeight="Bold" />
<!-- How can I make this image aware of the following button's state? -->
<Image Grid.Column="2" Source="/Resources/Star.Pressed.png" Visibility="{Binding RelativeSource={RelativeSource AncestorType=Grid}, Path={}}" Width="20" Height="20" />
<Button Grid.Column="2" x:Name="btnMakePrimary" Style="{StaticResource StarButton}" Command="{Binding ElementName=lstPhoneNumbers, Path=DataContext.MakePrimaryPhoneNumberCommand}" CommandParameter="{Binding}" ToolTip="Set as display number." Visibility="{Binding Path=IsEnabled, RelativeSource={RelativeSource Self}, Converter={StaticResource BoolVisibility}}" />
<Button Grid.Column="4" Style="{StaticResource DetailsButton}" Command="{Binding ElementName=lstPhoneNumbers, Path=DataContext.ViewPhoneNumberCommand}" CommandParameter="{Binding}" />
<Button Grid.Column="6" Style="{StaticResource DeleteButton}" Command="{Binding ElementName=lstPhoneNumbers, Path=DataContext.DeletePhoneNumberCommand}" CommandParameter="{Binding}" />
</Grid>
<Grid >
<Grid.ColumnDefinitions>
...
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Path=PhoneTypeString}" Style="{StaticResource FieldDataTextBlock}" />
<TextBlock Grid.Column="2" Text="(notes)" Foreground="Blue" ToolTip="{Binding Path=PhoneNumberNote}" Visibility="{Binding Path=HasNote, Converter={StaticResource BoolVisibility}}" />
</Grid>
</StackPanel>
</DataTemplate>
Either that, or is there a way to bind the image to a method in the parent datacontext that takes a parameter?
Thanks.
J
Never mind... I was able to make it happen via the ElementName attribute of the binding and fixing an issue with the included image resource which was messing with my visuals:
<Button Grid.Column="2" Name="btnMakePrimary" Style="{StaticResource StarButton}" Command="{Binding ElementName=lstPhoneNumbers, Path=DataContext.MakePrimaryPhoneNumberCommand}" CommandParameter="{Binding}" ToolTip="Set as display number." Visibility="{Binding Path=IsEnabled, RelativeSource={RelativeSource Self}, Converter={StaticResource BoolVisibility}}" />
<Image Grid.Column="2" Source="/Resources/Star.Pressed.png" Visibility="{Binding ElementName=btnMakePrimary, Path=IsEnabled, Converter={StaticResource BoolVisibilityReverse}}" Width="20" Height="20" />

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 apply Style of Parent control to Child controls in content template in Silverlight

Here My TextBox text is being bind to child text box in contentemplate but how to apply along with default style and validation errors to the child textbox in content template.
<TextBox x:Name="tbIdNumber" Width="110" Height="20" Text="{Binding IdNumber, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" >
<TextBox.Template>
<ControlTemplate TargetType="TextBox" >
<StackPanel Orientation="Horizontal" >
<Image Height="10" Width="20" Source="Images/bullet_darkblue.PNG" />
<TextBox Width="90" Tag="{Binding RelativeSource={RelativeSource TemplatedParent}}" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent},Path=DataContext, Mode=TwoWay}"
Text="{Binding Path=Text ,RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" >
</TextBox>
</StackPanel>
</ControlTemplate>
</TextBox.Template>
</TextBox>
It is very unusual to define the control template for TextBox control with a TextBox. I suggest you not pursue the path above.
You should instead start off with the default ControlTemplate for a TextBox here (Warning: it is very complex). It contains all the necessary visual states for validation, focused, etc.
From what I observe, you want to add an image next to the textbox. You should be able to add an image element inside the Grid and then perhaps adjust the margin on the Border. Here's a snippet:
<Image Height="10" Width="20" Source="Images/bullet_darkblue.PNG" />
<Border Margin="20,10,0,0"
x:Name="MouseOverBorder" BorderThickness="1" BorderBrush="Transparent">
<ScrollViewer x:Name="ContentElement" Padding="{TemplateBinding Padding}"
BorderThickness="0" IsTabStop="False"/>
</Border>

Item rendered via a DataTemplate with any Background Brush renders selection coloring behind item

I have a ListBox which uses a DataTemplate to render databound items. The XAML for the datatemplate is as follows:
<DataTemplate x:Key="NameResultTemplate">
<WrapPanel x:Name="PersonResultWrapper" Margin="0" Orientation="Vertical" Background="{Binding Converter={StaticResource NameResultToColor}, Mode=OneWay}" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<cmd:EventToCommand x:Name="SelectPersonEventCommand" Command="{Binding Search.SelectedPersonCommand, Mode=OneWay, Source={StaticResource Locator}}" CommandParameter="{Binding Mode=OneWay}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<TextBlock x:Name="txtPersonName" TextWrapping="Wrap" Margin="0" VerticalAlignment="Top" Text="{Binding PersonName}" FontSize="24" Foreground="Black" />
<TextBlock x:Name="txtAgencyName" TextWrapping="Wrap" Text="{Binding AgencyName}" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="0" FontStyle="Italic" Foreground="Black" />
<TextBlock x:Name="txtPIDORI" TextWrapping="Wrap" Text="{Binding PIDORI}" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="0" FontStyle="Italic" Foreground="Black" />
<TextBlock x:Name="txtDescriptors" TextWrapping="Wrap" Text="{Binding DisplayDescriptors}" Margin="0" VerticalAlignment="Top" Foreground="Black"/>
<Separator Margin="0" Width="400" />
</WrapPanel>
</DataTemplate>
Note that there is a value converter called NameResultToColor which changes the background brush of the rendered WrapPanel to gradient brush depending on certain scenarios.
All of this works as I'd expect, except when you click on any of the rendered ListBox items. When you click one, there is only the slightest sign of the selection coloring (the default bluish color). I can see a trace bit of it underneath my gradient-brushed item. If I reset the background brush to "no brush" then the selection rendering works properly. If I set the background brush to a solid color, it also fails to render as I'd expect.
How can I get the selection coloring to be on top? What is trumping the selection rendering?
The problem is that your item's template is being drawn over the selection being drawn by the ListBoxItem. If you want to ensure that the color is kept, you can add a DataTrigger to set the background of the WrapPanel to null when the item is selected:
<DataTemplate x:Key="NameResultTemplate">
<WrapPanel x:Name="PersonResultWrapper">
...
</WrapPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" Value="True">
<Setter TargetName="PersonResultWrapper" Property="Background" Value="{x:Null}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>

Resources