How to declare resource before Window in XAML? - c#

My code:
<Window ...
Title="Notification" Height="90" Width="300" ResizeMode="NoResize" WindowStyle="None" DataContext="{Binding Notification, Source={StaticResource Locator}}" Opacity="{Binding TransitionOpacity}" Left="{Binding LeftMargin}" Top="{Binding TopMargin}" Visibility="{Binding IsVisible, Converter={StaticResource BoolToVisibility}}">
<Window.Resources>
<local:BoolToVisibleOrHidden x:Key="BoolToVisibility" />
</Window.Resources>
<Grid Background="#FF3C4759">
...
</Window>
While compiling I get exception System.Windows.Markup.XamlParseException and after change code to
<Window ...
Title="Notification" Height="90" Width="300" ResizeMode="NoResize" WindowStyle="None" DataContext="{Binding Notification, Source={StaticResource Locator}}" Opacity="{Binding TransitionOpacity}" Left="{Binding LeftMargin}" Top="{Binding TopMargin}" >
<Window.Resources>
<local:BoolToVisibleOrHidden x:Key="BoolToVisibility" />
</Window.Resources>
<Grid Background="#FF3C4759" Visibility="{Binding IsVisible, Converter={StaticResource BoolToVisibility}}">
...
</Window>
it works but I want to set Window visibility instead of Grid.

Binding window visibility might be not a good idea in this case. If you have a notification which you want to hide after some time - just close it (Close()) instead of hiding.
If however you still want to do this - put converter into your application ( App.xaml file). Then you will be able to use it in Window.Visibility binding. As of now - window Visibility property is set before Window.Resources are initialized, so you cannot use converter created inside Window.Resources.
Alternative way is to set Visibility like this:
<Window.Resources>
<local:BoolToVisibleOrHidden x:Key="BoolToVisibility" />
</Window.Resources>
<Window.Visibility>
<Binding Path="IsVisible" Converter="{StaticResource BoolToVisibility}" />
</Window.Visibility>

Related

ChangePropertyAction behaviour does not work on Popup with a custom control

Hi i have the following window, it has a button, and when i click on it, it shows a popup that contains some text. When the popup is closed, the behaviour cleans the text inside the popup
<Window
x:Class="WpfTests.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:behaviours="http://schemas.microsoft.com/xaml/behaviors"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfTests"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="300"
Height="300"
mc:Ignorable="d">
<StackPanel
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="Red"
Orientation="Vertical">
<ToggleButton
x:Name="CustomButton"
Width="40"
Height="40"
Content="Checkbutton" />
<Popup
IsOpen="{Binding ElementName=CustomButton, Path=IsChecked}"
Placement="Bottom"
PlacementTarget="{Binding ElementName=CustomButton}"
StaysOpen="False">
<behaviours:Interaction.Triggers>
<behaviours:EventTrigger EventName="Closed">
<behaviours:ChangePropertyAction
PropertyName="Text"
TargetObject="{Binding ElementName=UrlTextBox}"
Value="" />
</behaviours:EventTrigger>
</behaviours:Interaction.Triggers>
<TextBlock
x:Name="UrlTextBox"
Width="100"
Height="100"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="Green"
Foreground="White"
Text="A url" />
</Popup>
</StackPanel>
Now, if i change the child of the popup to a user control like the following:
<Popup
IsOpen="{Binding ElementName=CustomButton, Path=IsChecked}"
Placement="Bottom"
PlacementTarget="{Binding ElementName=CustomButton}"
StaysOpen="False">
<behaviours:Interaction.Triggers>
<behaviours:EventTrigger EventName="Closed">
<behaviours:ChangePropertyAction
PropertyName="Text"
TargetObject="{Binding ElementName=CustomControl, Path=UrlTextBox}"
Value="" />
</behaviours:EventTrigger>
</behaviours:Interaction.Triggers>
<local:CustomControl x:Name="CustomControl" />
</Popup>
CustomControl:
<UserControl
x:Class="WpfTests.CustomControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfTests"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<TextBlock
x:Name="UrlTextBox"
Width="100"
Height="100"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="Green"
Foreground="White"
Text="A url" />
The behaviour crashes, because it cannot find the property text and i don't know why.
I know i can do this using code behind, but i would like to do it in the xaml.
Any help would be appreciated
This line isn't going to work
TargetObject="{Binding ElementName=CustomControl, Path=UrlTextBox}"
Because the Path part needs to point to a Property (the TextBlock inside the UserControl is compiled as a public field).
You need to add a line in you UserControl code-behind like this:
public TextBlock UrlText => this.UrlTextBox;
and then in your behaviour change it to this
TargetObject="{Binding ElementName=CustomControl, Path=UrlText}"

Force transparent background on custom UserControl

I want to create a new UserControl and reroute the Background property to use it elsewhere than in the UserControl.Background property (like it is done on the checkbox for example).
Here is a simple custom usercontrol:
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Controls"
xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"
x:Class="Controls.HexagonalTile"
mc:Ignorable="d" d:DesignWidth="300" d:DesignHeight="300">
<Grid>
<ed:RegularPolygon Fill="{Binding ElementName=LayoutRoot, Path=Background}" StrokeThickness="5" Stroke="Black"/>
</Grid>
And I want to use it like this:
<Controls:HexagonalTile HorizontalAlignment="Left" Height="100" Width="100" Background="Aqua" />
But when I do this, the corner of my user control, outside of the hexagone, take the background color too. I want them to stay transparent.
Thank's for your help.
The reason why this is happening is because the default ControlTemplate for a UserControl has a Border with a TemplateBinding to the Background property.
However, you can re-template the control like this to achieve your goal:
<UserControl x:Class="WpfApp4.HexagonalTile"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing">
<UserControl.Template>
<ControlTemplate TargetType="{x:Type UserControl}">
<Grid>
<ContentPresenter />
</Grid>
</ControlTemplate>
</UserControl.Template>
<Grid>
<ed:RegularPolygon
Fill="{Binding Background, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
Stroke="Black"
StrokeThickness="5" />
</Grid>
</UserControl>
I hope this helps!

Binding visibility of usercontrol does not collapse control

i do have a problem with binding the visibility of my usercontrol.
The binding to a Dependency Property of type Visibility works fine and the correct value (in this case Collapsed) is held by the DP. The content of my Grid within the UserControl is set to collapsed, but the hole control doesnt collapse. It still keeps the space occupied defined by with and heigth, as referenced in the xaml.
EDIT: i found out, that the problem is that i set width and height in the xaml where i reference my usercontrol. if i don't do this, the control collapses correct (therefore binding works fine). But i need to set width and heigth in case the usercontrol is visible.
Any idea how i can solve this problem?
<my:MenuButtonBase x:Class="bxSuite.Controls.MenuButtonLarge"
xmlns:my="clr-namespace:bxSuite.Controls"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Background="Black"
>
<Grid Visibility="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=ButtonVisibility}" >
<StackPanel>
<Image Source="{Binding ButtonImageSource}" Margin="5,10,5,5" Width="48" Height="48" VerticalAlignment="Top" HorizontalAlignment="Center" />
<TextBlock Text="{Binding FunctionHeader}" Foreground="White" TextWrapping="Wrap" TextAlignment="Center" Padding="5,5,5,5" FontSize="12" />
</StackPanel>
</Grid>
</my:MenuButtonBase>
In XAML i reference my usercontrol like this (where the Converter produces the visibility-state correctly):
<my:MenuButtonLarge Name="btnInEuqipment" ButtonVisibility="{Binding Path=User, Converter={StaticResource ConverterUserRightVisibility}, ConverterParameter=5}" VerticalAlignment="Top" FunctionHeader="{lex:Loc Key=MenuButton_InEquipment}" Width="130" ButtonImageSource="/bxSuite.RolloutManager;component/Images/inequipment_48x48.png" BackgroundEnabled="#FF0694FD" BackgroundHover="#FF0072C6" MenuButtonClick="btnInEuqipment_MenuButtonClick" Height="95" Margin="5,10,0,0" />
Try set the visibility of the user control instead of the grid, should work.
Your code should be like this.
<my:MenuButtonBase x:Class="bxSuite.Controls.MenuButtonLarge"
xmlns:my="clr-namespace:bxSuite.Controls"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Visibility="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=ButtonVisibility}"
Background="Black">
<Grid>
<StackPanel>
<Image Source="{Binding ButtonImageSource}"
Margin="5,10,5,5"
Width="48"
Height="48"
VerticalAlignment="Top"
HorizontalAlignment="Center" />
<TextBlock Text="{Binding FunctionHeader}"
Foreground="White"
TextWrapping="Wrap"
TextAlignment="Center"
Padding="5,5,5,5"
FontSize="12" />
</StackPanel>
</Grid>
Dont forget to update the RelativeSource of your bind.

how to bind fontsize for wpf textbox?

I have a textbox control that works appropriately, without binding, while its font size should be changed dynamically.
I wanted to do it right and work using binding.
I tried to bind the FontSize using (xaml):
<UserControl x:Class="<ClassName>"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" Focusable="True"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBox x:Name="_textBox" Visibility="Visible" xml:space="preserve"
Background="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type UserControl}},Path=Background}"
Foreground="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type UserControl}},Path=Foreground}"
FontFamily="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type UserControl}},Path=FontFamily}"
BorderBrush="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type UserControl}},Path=BorderBrush}"
Text="{Binding MultilineText}"
FontSize="{Binding Path=MultilineFontSize}"
KeyUp="_textBox_KeyUp"
PreviewTextInput="_textBox_PreviewTextInput"
DataObject.Pasting="_textBox_Pasting"
VerticalContentAlignment="Top"
PreviewKeyDown="TextBox_OnPreviewKeyDown"
TextWrapping="Wrap"
ScrollViewer.VerticalScrollBarVisibility="Visible"
/>
</Grid>
and in the code behind:
private double _multilineFontSize;
public double MultilineFontSize
{
get { return GetBestFittingFontSize(); }
set
{
if (value != _multilineFontSize)
{
_multilineFontSize = value;
OnPropertyChanged("MultilineFontSize");
}
}
}
The only use for _multilineFontSize is to replace _textbox.Text wherever I used it (in events etc).
GetBestFittingFontSize() is a function (that works appropriately) and calculates the font size I need to use. Take it as given. It returns double.
It doesn't work. Does any one have any idea why? (maybe some DataContext issues?)
You can try to use the ViewBox which can be used to scale its content.
<Viewbox StretchDirection="Both" Stretch="Uniform">
<local:UserControl1 Height="100" Width="100"/>
</Viewbox>

How to bind an element to a property which belongs to the root element of a control?

The question may sound a little confusing, but the problem I'm currently facing is this:
<Button x:Class="sandbox.BtnLabel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
x:Name="this">
<Button.ToolTip>
<TextBlock Background="Yellow" Text="{Binding ElementName=this, Path=LabelText}"/>
</Button.ToolTip>
<TextBlock Background="Yellow" Text="{Binding ElementName=this, Path=LabelText}"/>
</Button>
Only the second binding works, which sets the content of the button. The first one, which I would like to use to set the contents of the tooltip of the button (via the LabelText dependency property) does not work.
Is it possible to make the first binding work?
Thanks.
Try this:
<Button x:Class="sandbox.BtnLabel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="this">
<Button.ToolTip>
<ToolTip DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}">
<TextBlock Background="Yellow"
Text="{Binding LabelText}" />
</ToolTip>
</Button.ToolTip>
<TextBlock Background="Yellow"
Text="{Binding ElementName=this,
Path=LabelText}" />
</Button>
We add a ToolTip element and assign it's DataContext as it's PlacementTarget which should then reach the TextBlock

Categories