How to correctly use a UserControl in WPF? - c#

I created this user control
<UserControl x:Class="POS1.Windows.Controles.txttransparente"
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"
Height="auto" Width=" auto"
>
<Border BorderBrush="Yellow" Background="Transparent" CornerRadius="10,10,10,10" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2">
<TextBox Name="txt1" Background="Transparent" BorderBrush="Black" BorderThickness="3" Text="Usuario" FontSize="20" FontWeight="ExtraBold" ></TextBox>
</Border>
</UserControl>
When I add it to a Window,
<Controls:MetroWindow
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:Custom="http://modernwpf" xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
x:Class="POS1.MainWindow"
xmlns:txt="clr-namespace:POS1.Windows.Controles"
Title="MainWindow" Height="292" Width="535" AllowsTransparency="True" WindowStyle="None"
>
<Grid>
<Grid.RowDefinitions >
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions >
<ColumnDefinition Width="133*"/>
<ColumnDefinition Width="134*"/>
<ColumnDefinition Width="135*"/>
<ColumnDefinition Width="133*"/>
</Grid.ColumnDefinitions>
<Border Grid.ColumnSpan="4" Grid.RowSpan="7" CornerRadius="40,50,60,70">
<Border.Background>
<ImageBrush ImageSource="pack://siteoforigin:,,,/Resources/b.jpg"/>
</Border.Background>
</Border>
<Border BorderBrush="Yellow" Background="Transparent" CornerRadius="10,10,10,10" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2">
<TextBox Background="Transparent" BorderBrush="Black" BorderThickness="3" Text="Usuario" FontSize="20" FontWeight="ExtraBold" ></TextBox>
</Border>
<TextBox Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" Text="Contraseña" FontSize="20" FontWeight="ExtraBold" ></TextBox>
<Button Grid.Row="5" Grid.Column="1" Content="Aceptar" FontSize="12" FontWeight="ExtraBold" ></Button>
<Button Grid.Row="5" Grid.Column="2" Content="Olvidé contraseña" FontSize="12" FontWeight="ExtraBold" ></Button>
<txt:txttransparente Content=" Hola Mundo" Grid.Row="6" Grid.Column="1" Grid.ColumnSpan="2" ></txt:txttransparente>
</Grid>
</Controls:MetroWindow>
as you see I could not modify the txt1.Text, so I have instead used Content="hola mundo"
However this sees it as above, but not as similar to the button usuario.

Without explicitly navigating the control's visual tree, the elements in your UserControl need for you to implement mechanism to pass data from client code using your control to the elements contained within. A common strategy for doing this is to simply declare a property on your UserControl type itself, and then bind the appropriate member in the control's tree to that property.
For example:
class txttransparente : UserControl
{
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text", typeof(string), typeof(txttransparente));
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
}
Then in your XAML for the UserControl:
<UserControl x:Class="POS1.Windows.Controles.txttransparente"
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:POS1.Windows.Controles"
mc:Ignorable="d"
Height="auto" Width=" auto">
<Border BorderBrush="Yellow" Background="Transparent" CornerRadius="10,10,10,10"
Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2">
<TextBox Name="txt1" Background="Transparent" BorderBrush="Black"
BorderThickness="3"
Text="{Binding Text,
RelativeSource={RelativeSource AncestorType={x:Type local:
txttransparente}}}"
FontSize="20"
FontWeight="ExtraBold"/>
</Border>
</UserControl>
Note the change not only in the binding for the TextBox.Text property there, but also the addition of the xmlns:local declaration, so that the binding can find the parent UserControl object where the property exists.
These changes create the property, and connect it to the Text property of the control's TextBox element.
Then finally, where you use the UserControl, you simply set the Text property (instead of Content):
<txt:txttransparente Text="Hola Mundo" Grid.Row="6" Grid.Column="1" Grid.ColumnSpan="2"/>

Related

how to make a side bar in WPF

I've came across a problem where I'm trying to make a side bar in WPF. I've made the grid area for it and it seems to exist however when I try to put a label on it the label seems to be hidden behind the grid. I tried using z-index to no prevail however if I use a margin to move the text to the top of the form then it appears.
Red - The top of the form and where the form name is. (This is how the top is supposed to look
Orange - The left size is where the side bar is meant to be and the right is where messages will be shown.
Grey - By using a margin and moving the text up you can see that is displayed at the top where the name of the form
should be.
This is **not** how its supposed and should be where the
yellow is however it shows that if anything goes where the yellow is then
it is covered by the gray area as if it has a higher z-index.
My xaml is bellow
<Window x:Class="CrackleChat.MainWindow"
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"
xmlns:local="clr-namespace:CrackleChat" xmlns:viewmodel="clr-namespace:CrackleChat.MVVM.ViewModel"
mc:Ignorable="d"
Height="650" Width="1200" Icon="/Icon.png"
Background="#36393F"
WindowStyle="None"
AllowsTransparency="True"
ResizeMode="CanResizeWithGrip">
<Window.DataContext>
<viewmodel:MainViewModel></viewmodel:MainViewModel>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="25">
</RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200">
</ColumnDefinition>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border Grid.ColumnSpan="2" Background="#252525" MouseDown="Border_MouseDown" Panel.ZIndex="1">
<Grid HorizontalAlignment="Stretch">
<Label Content="Crackle Chat" Foreground="Gray" FontWeight="SemiBold"/>
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<Button Width="20" Height="20" Content="🗕" Background="Transparent"
BorderThickness="0" Foreground="Gray" FontWeight="Bold" Margin="0,0,0,3"
Click="Button_Minimize_Click"></Button>
<Button Width="20" Height="20" Content="🗖" Background="Transparent"
BorderThickness="0" Foreground="Gray" FontWeight="Bold"
Click="Button_Maximize_Click"></Button>
<Button Width="20" Height="20" Content="╳" Background="Transparent"
BorderThickness="0" Foreground="Gray" FontWeight="Bold"
Click="Button_Exit_Click"></Button>
</StackPanel>
</Grid>
</Border>
<Grid Background="#2F3136">
<!--This is the left hand column-->
<Grid.RowDefinitions>
<RowDefinition Height="25"></RowDefinition>
<RowDefinition Height="0*"/>
</Grid.RowDefinitions>
<ListView ItemsSource="{Binding Contacts}" Background="Transparent" BorderThickness="0"
Grid.Row="1" ItemContainerStyle="{StaticResource ContactCard}"></ListView>
</Grid>
<Label Panel.ZIndex="5" Content="Contacts" VerticalAlignment="Top" FontWeight="Medium" Foreground="Gray" Height="26" Margin="0,25,0,0"/>
</Grid>
</Window>
For your second subgrid add this: Grid.Row = "1" Otherwise both grids are in the same row (0 based index applies here)
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition Height="*"/> <!--This is your second row-->
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200">
</ColumnDefinition>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border Grid.ColumnSpan="2" Background="#252525" MouseDown="Border_MouseDown" Panel.ZIndex="1">
<Grid HorizontalAlignment="Stretch">
<Label Content="Crackle Chat" Foreground="Gray" FontWeight="SemiBold"/>
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<Button Width="20" Height="20" Content="🗕" Background="Transparent"
BorderThickness="0" Foreground="Gray" FontWeight="Bold" Margin="0,0,0,3"
Click="Button_Minimize_Click"></Button>
<Button Width="20" Height="20" Content="🗖" Background="Transparent"
BorderThickness="0" Foreground="Gray" FontWeight="Bold"
Click="Button_Maximize_Click"></Button>
<Button Width="20" Height="20" Content="╳" Background="Transparent"
BorderThickness="0" Foreground="Gray" FontWeight="Bold"
Click="Button_Exit_Click"></Button>
</StackPanel>
</Grid>
</Border>
<Grid Background="#2F3136" Grid.Row="1"> <!--This goes to the second row-->
<!--This is the left hand column-->
<Grid.RowDefinitions>
<RowDefinition Height="25"></RowDefinition>
<RowDefinition Height="0*"/>
</Grid.RowDefinitions>
<ListView ItemsSource="{Binding Contacts}" Background="Transparent" BorderThickness="0"
Grid.Row="1" ItemContainerStyle="{StaticResource ContactCard}"></ListView>
</Grid>
<Label Panel.ZIndex="5" Content="Contacts" VerticalAlignment="Top" FontWeight="Medium" Foreground="Gray" Height="26" Margin="0,25,0,0"/>
</Grid>
Edit: added modified code for better explanation.

Change content stack panel dynamically with button click WPF

I would like to change stack panel content/data on button click in the same window.
I have a menu list on left and on the right of the window I have 2 stackpanel which I want to update. This is actually my configuration screen. Following is my XAML code:
<Window x:Class="Manager.Screens.Configurations"
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"
xmlns:local="clr-namespace:Manager.Screens"
mc:Ignorable="d"
Title="Configurations" Height="850" Width="1000" WindowStyle="None" >
<Border
BorderBrush="Black"
BorderThickness="0"
Padding="0">
<Grid Background="White" ShowGridLines="True" Margin="-3,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200*"/>
<ColumnDefinition Width="263*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" Name="StackPanel1" VerticalAlignment="Top" Height="Auto" Width="Auto">
<Image Source="Resources\Images\config_back.jpg" Stretch="Fill" Opacity="0.65" Height="Auto" Margin="-3,-2,0,0"/>
<Button Margin="0,-1450,0,60" Height="38" Background="Transparent">
<StackPanel Orientation="Horizontal" Width="332">
<Image Source="Resources\Images\tools.png" Margin="75,0,25,0"/>
<TextBlock Text="General" VerticalAlignment="Center" FontSize="18" FontWeight="Bold" Foreground="#FFFF8C3D"/>
</StackPanel>
</Button>
<Button Margin="0,-1350,0,10" Height="38" Background="Transparent">
<StackPanel Orientation="Horizontal" Width="332">
<Image Source="Resources\Images\setting.png" Margin="75,0,25,0"/>
<TextBlock Text="Settings" VerticalAlignment="Center" FontSize="18" FontWeight="Bold" Foreground="#FFFF8C3D"/>
</StackPanel>
</Button>
<Button Margin="0,-1250,0,-40" Height="38" Background="Transparent">
<StackPanel Orientation="Horizontal" Width="332">
<Image Source="Resources\Images\user.png" Margin="75,0,25,0"/>
<TextBlock Text="Limits/Stations" VerticalAlignment="Center" FontSize="18" FontWeight="Bold" Foreground="#FFFF8C3D"/>
</StackPanel>
</Button>
<Button Margin="0,-1150,0,-90" Height="38" Background="Transparent">
<StackPanel Orientation="Horizontal" Width="332">
<Image Source="Resources\Images\user.png" Margin="75,0,25,0"/>
<TextBlock Text="Portions" VerticalAlignment="Center" FontSize="18" FontWeight="Bold" Foreground="#FFFF8C3D"/>
</StackPanel>
</Button>
<Button Margin="0,-1050,0,-140" Height="38" Background="Transparent">
<StackPanel Orientation="Horizontal" Width="332">
<Image Source="Resources\Images\user.png" Margin="75,0,25,0"/>
<TextBlock Text="Label Templates" VerticalAlignment="Center" FontSize="18" FontWeight="Bold" Foreground="#FFFF8C3D"/>
</StackPanel>
</Button>
<Button Margin="0,-950,0,-190" Height="38" Background="Transparent">
<StackPanel Orientation="Horizontal" Width="332">
<Image Source="Resources\Images\user.png" Margin="75,0,25,0"/>
<TextBlock Text="RFID Containers" VerticalAlignment="Center" FontSize="18" FontWeight="Bold" Foreground="#FFFF8C3D"/>
</StackPanel>
</Button>
<Button Margin="0,-850,0,-240" Height="38" Background="Transparent">
<StackPanel Orientation="Horizontal" Width="332">
<Image Source="Resources\Images\user.png" Margin="75,0,25,0"/>
<TextBlock Text="User Management" VerticalAlignment="Center" FontSize="18" FontWeight="Bold" Foreground="#FFFF8C3D"/>
</StackPanel>
</Button>
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="0" HorizontalAlignment="Stretch" Name="StackPanel2" VerticalAlignment="Top" Orientation="Vertical">
</StackPanel>
<StackPanel Grid.Column="2" Grid.Row="0" HorizontalAlignment="Left" Name="StackPanel3" VerticalAlignment="Top">
<TextBlock FontSize="18" HorizontalAlignment="Center" Margin="0,0,0,15">StackPanel3</TextBlock>
<Button Margin="10">Button 7</Button>
<Button Margin="10">Button 8</Button>
<Button Margin="10">Button 9</Button>
<TextBlock>ColumnDefinition.Width="Auto"</TextBlock>
<TextBlock>StackPanel.HorizontalAlignment="Left"</TextBlock>
<TextBlock>StackPanel.VerticalAlignment="Top"</TextBlock>
<TextBlock>StackPanel.Orientation="Vertical"</TextBlock>
<TextBlock>Button.Margin="10"</TextBlock>
</StackPanel>
</Grid>
</Border>
</Window>
I haven't written any controls or functions so far please help me as I am new how can it be done in WPF.
Basically there are three main approaches to show / hide controls on your view. Here's the code that provides you with an example of each:
XAML:
<Window x:Class="WpfApp1.MainWindow"
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"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0" Grid.Row="0" Visibility="{Binding IsBlueRectangleVisible, Converter={StaticResource BooleanToVisibilityConverter}}" Fill="Blue" />
<Button Grid.Column="1" Grid.Row="0" Content="Binding to ViewModel" Command="{Binding BlueRectangleSwitchCommand}"/>
<Rectangle Grid.Column="0" Grid.Row="1" Visibility="{Binding ElementName=toggleBtn, Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}" Fill="Red" />
<ToggleButton Grid.Column="1" Grid.Row="1" x:Name="toggleBtn" Content="Toggle switch" />
<Rectangle x:Name="greenRectangle" Grid.Column="0" Grid.Row="2" Fill="Green" />
<Button Grid.Column="1" Grid.Row="2" Content="Code behind" Click="GreenRectangleBtnClick"/>
</Grid>
</Window>
Code behind:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
// Blue rectangle
// Initialize the command that is binded to one of your buttons
BlueRectangleSwitchCommand = new RelayCommand(o =>
{
// Switches the flag binded to Visibility property of one of your Rectangles
IsBlueRectangleVisible = !IsBlueRectangleVisible;
// Notify that UI shoud be re-rendered
OnPropertyChanged(nameof(IsBlueRectangleVisible));
});
// Next line is needed in order to bind this object to the DataContext of itself (wierd, isn't it?)
// So the MainWindow would know where to llok up for the properties you are binding to in XAML
DataContext = this;
}
// Blue rectangle
// Property that is binded to Visibility property of one of your Rectangles
public bool IsBlueRectangleVisible { get; set; }
// Blue rectangle
// Property that is binded to Command property of one of your Rectangles
public ICommand BlueRectangleSwitchCommand { get; private set; }
// Blue rectangle
// This implementation of INotifyPropertyChanged interface allows you to use OnPropertyChanged
// that is needed for notifying UI that your properties changed
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
#endregion
// Green rectangle
private void GreenRectangleBtnClick(object sender, RoutedEventArgs e)
{
greenRectangle.Visibility = greenRectangle.Visibility == Visibility.Visible
? Visibility.Collapsed
: Visibility.Visible;
}
}
I added commentaries so you could easily distinguish between each of them. As it's up to you to decide which one suits you more.
But here's what I suggest:
If you don't need to track the actual state, use the Toggle switch (Red);
If you need to track the state of the switch or to switch if from your code behind - use Binding to ViewModel (Blue);
Never use the third one. Okay, this is a joke, sort of. If you need a really simple UI in a small application - use it all you want. But if there's a possibility that your app is going to grow so you'll need a separation of concerns, test-ability, etc, don't even look to this approach. It'll make your application a noodle pan (Green).

How to make WPF Toolkit charts expand with to fit content?

I'm trying to create some bar charts from DotNetProjects.Wpf.Toolkit that display some data totals, though the data can change at run time. The problem is that I cannot get the chart to fit the size of the content - I always have to provide a fixed value (and setting Height="Auto" doesn't work), but I don't know what the size will need to be while running. What can I do to make my chart fit the content rather than the other way around?
My XAML code looks like this:
<Window
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"
xmlns:local="clr-namespace:Movie_Vault"
xmlns:Controls="clr-namespace:System.Windows.Controls;assembly=DotNetProjects.Layout.Toolkit" xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit" x:Class="Movie_Vault.frmStatistics"
mc:Ignorable="d"
Title="frmStatistics" Style="{StaticResource RoundedFormStyle}" WindowStartupLocation="CenterOwner">
<Border Style="{StaticResource WindowBorderStyle}">
<DockPanel x:Name="OuterPanel" >
<Border Style="{StaticResource PanelBorderStyle}" DockPanel.Dock="Top">
<DockPanel x:Name="TopPanel" HorizontalAlignment="Stretch" VerticalAlignment="Top">
<Image Height="16" Margin="8,4,8,4" Source="Images/process.png"/>
<TextBlock Style="{StaticResource MediumFont}"><Run Text="Statistics"/></TextBlock>
<DockPanel DockPanel.Dock="Right" HorizontalAlignment="Right" VerticalAlignment="Center">
<Button x:Name="btnClose" Content="X" Style="{StaticResource MicroButtonStyle}" Margin="0,0,8,0" Click="btnClose_Click"/>
</DockPanel>
</DockPanel>
</Border>
<Border Style="{StaticResource PanelBorderStyle}" DockPanel.Dock="Left" Margin="0,8,0,0">
<DockPanel VerticalAlignment="Top" >
<ScrollViewer VerticalScrollBarVisibility="Auto" Height="400" Width="500">
<Grid Name="panelTopGenres">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<toolkit:Chart Name="chartTopGenres" Title="Top Genres" VerticalAlignment="Top"
Margin="16,16,16,8" Padding="8" Background="White" >
<toolkit:BarSeries DependentValuePath="Value" IndependentValuePath="Key"
ItemsSource="{Binding}"
IsSelectionEnabled="False" Background="White"/>
</toolkit:Chart>
<Button Grid.Row="1" x:Name="btnTopGenresToggle" Style="{StaticResource SmallButtonStyle}"
Content="Show All Genres" Width="120"
Margin="16,0,4,4" HorizontalAlignment="Left" Click="btnToggle_Click" />
</Grid>
</ScrollViewer>
</DockPanel>
</Border>
</DockPanel>
</Border>
</Window>
What can I do to make my chart fit the content rather than the other way around?
Get rid of any StackPanels:
<Grid Name="panelTopGenres">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<toolkit:Chart Name="chartTopGenres" Title="Top Genres" VerticalAlignment="Top"
Margin="16,16,16,8" Padding="8" Background="White" >
<toolkit:BarSeries DependentValuePath="Value" IndependentValuePath="Key"
ItemsSource="{Binding}"
IsSelectionEnabled="False" Background="White"/>
</toolkit:Chart>
<Button Grid.Row="1" x:Name="btnTopGenresToggle" Style="{StaticResource SmallButtonStyle}"
Content="Show All Genres" Width="120"
Margin="16,0,4,4" HorizontalAlignment="Left" Click="btnToggle_Click" />
</Grid>
A StackPanel doesn't resize its children.

How can I update this element from the viewmodel

I'm using Material Design toolkit and I want to somehow set the DrawerHost to open or closed from the view model with a property. I have a property in the view model that is already updated from another source. I just need to translate that property to the xaml. Any help appreciated.
<UserControl x:Class="GS.Server.Focuser.FocuserView"
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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d">
<materialDesign:DrawerHost HorizontalAlignment="Stretch" VerticalAlignment="Stretch" BorderThickness="2"
IsLeftDrawerOpen="{Binding ElementName=MenuToggleButton, Path=IsChecked}"
BorderBrush="{DynamicResource MaterialDesignDivider}">
<materialDesign:DrawerHost.LeftDrawerContent>
<Grid Width="700">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<ToggleButton DockPanel.Dock="Top" HorizontalAlignment="Right" Margin="5"
Style="{StaticResource MaterialDesignHamburgerToggleButton}"
Command="{x:Static materialDesign:DrawerHost.CloseDrawerCommand}"
CommandParameter="{x:Static Dock.Left}"
IsChecked="{Binding ElementName=MenuToggleButton, Path=IsChecked, Mode=TwoWay}"/>
</StackPanel>
<Label Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Center">Focuser Settings Go Here</Label>
</Grid>
</materialDesign:DrawerHost.LeftDrawerContent>
<Grid >
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<ToggleButton Grid.Row="0" HorizontalAlignment="Left" VerticalAlignment="Top"
Command="{x:Static materialDesign:DrawerHost.OpenDrawerCommand}"
CommandParameter="{x:Static Dock.Left}"
Style="{StaticResource MaterialDesignHamburgerToggleButton}" IsChecked="False"
x:Name="MenuToggleButton"/>
<TextBlock Grid.Row="1" Text="This is the Focuser Page"
FontWeight="Bold" FontSize="18"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</materialDesign:DrawerHost>

Value converter is not triggered within user control if used as list box item

To display a WPF list box, I use a user control (MessageRowTemplate) as list box item. The user contrul uses a value converter (MessageTypeToBrushConverter). For some reason, the value converter is only trigered if the user control isn't used as list box item but seperate.
xaml-file with user control used seperately and inside a list box as list box item:
<local:MuuriWindow x:Class="Muuri_UI_WPFv3.Window_Conversation"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Muuri_UI_WPFv3"
Loaded="EventHandler_WindowLoaded">
<Window.Resources>
<DataTemplate x:Key="ResponsesListTemplate">
<local:MessageRowTemplate Margin="3" />
</DataTemplate>
<local:MessageTypeToBrushConverter x:Key="converter" />
</Window.Resources>
<StackPanel Orientation="Vertical">
<local:MessageRowTemplate x:Name="questionControl" />
<ListBox HorizontalAlignment="Stretch" ItemTemplate="{DynamicResource ResponsesListTemplate}" ItemsSource="{Binding}" Name="listBoxResponses" Height="200" ScrollViewer.VerticalScrollBarVisibility="Visible" Style="{StaticResource MuuriListboxStyle}" />
<StackPanel Orientation="Horizontal">
<Button Name="buttonReply" Click="EventHandler_ButtonReplyClicked">Reply</Button>
<Button Name="buttonCancel" Click="EventHandler_ButtonCancelClicked">Cancel</Button>
</StackPanel>
</StackPanel>
</local:MuuriWindow>
And here's the MessageRowTemplate.xaml:
<UserControl x:Class="Muuri_UI_WPFv3.MessageRowTemplate"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Muuri_UI_WPFv3"
Width="300"
Loaded="UserControl_Loaded">
<UserControl.Resources>
<local:MessageTypeToBrushConverter x:Key="converter" />
</UserControl.Resources>
<Grid Margin="2,1,2,1" VerticalAlignment="Top" Height="auto">
<Grid.RowDefinitions>
<RowDefinition Height="2" />
<RowDefinition Height="0.5*" />
<RowDefinition Height="0.5*" />
<RowDefinition Height="2" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="15"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Name="leftBorder" Margin="2,2,0,2" Grid.RowSpan="4" CornerRadius="3,0,0,3" Panel.ZIndex="1" Background="{Binding Path=Type, Converter={StaticResource converter}}" />
<Border Margin="0,0,0,0" Grid.Column="1" Grid.ColumnSpan="2" Grid.RowSpan="4" Background="#FF666666" CornerRadius="0,5,5,0" />
<Border Margin="0,0,0,0" Grid.ColumnSpan="2" Grid.RowSpan="4" Background="{x:Null}" BorderThickness="2,2,2,2" BorderBrush="#FF202020" CornerRadius="5,5,5,5" Panel.ZIndex="0" />
<TextBlock Padding="5,2,5,2" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Text="{Binding Path=Text}" Grid.Row="1" Grid.Column="1" Foreground="White" />
<TextBlock Padding="5,2,5,2" HorizontalAlignment="Stretch" VerticalAlignment="Center" Text="{Binding Path=Author}" Grid.Row="2" Grid.Column="1" Foreground="White" />
</Grid>
</UserControl>
As you might guess, the value converter is responsible for converting some value to a brush. It works fine for this <local:MessageRowTemplate x:Name="questionControl" /> but not for the list box item.
Google didn't give me any hints for keyword combinations of 'list box', 'list box item', 'user control', 'value converter'.
Do you have an idea?
Thanks in advace.
The list box
<ListBox HorizontalAlignment="Stretch" ItemTemplate="{DynamicResource ResponsesListTemplate}" ItemsSource="{Binding}" Name="listBoxResponses" Height="200" ScrollViewer.VerticalScrollBarVisibility="Visible" Style="{StaticResource MuuriListboxStyle}" />
uses the local resource ResponsesListTemplat which again uses the MessageRowTemplate.
The converter is used within this template:
<UserControl.Resources>
<local:MessageTypeToBrushConverter x:Key="converter" />
</UserControl.Resources>
and applied to the first border-tag within the template.

Categories