WPF Button from Controltemplate isn't visible - wpf

I want to instantiate two Controls (an Expander and a Button) from two ControlTemplates. They are docked in a Dockpanel (right and left). The Expander is visible and it works fine, but the Button isn't visible.
The ControlTemplate of the Button in App.xaml:
...
<ControlTemplate x:Key="OpenFileButton" TargetType="{x:Type Button}">
<Image Name="OpenFileButton" Source="F:\AudioNodeGUI_XAML\images\filebutton.jpg">
</Image>
</ControlTemplate>
...
And the instantiation in a usercontrol:
<Grid>
<Image Source="F:\AudioNodeGUI_XAML\images\FileInputNode.jpg"/>
<DockPanel Name="dock" Width="151" Height="20" Margin="27,53,122,139">
<Expander Name="expander" Template="{StaticResource FileExpander}" Height="20" Width="41" PreviewMouseLeftButtonUp="expand" DockPanel.Dock="Left">
<ListView Name="usedFiles" Background="Black" BorderBrush="Transparent" BorderThickness="0" Width="140" Height="120" Opacity="0.5">
</ListView>
</Expander>
<Button Name="OpenFileButton" Template="{StaticResource OpenFileButton}" DockPanel.Dock="Right" />
</DockPanel>
</Grid>
But the Button isn't visible, neither in the Designer (just the outline) nor in execution. What am I doing wrong?

I suspect that your issue is just incorrect path to the image file. Unfortunately you won't have any tip about this kind of error neither in designer nor in output window. However if you have ReSharper it should highlight the path to the file if it doesn't exist

Related

WPF how to set stackpanel as resources and reuse it in TabControls

I am new to C# and WPF so please give me some ideas:
I have an WPF app used to display some stack panels,all stack panels default Visibility is set to collapsed and they will switch to visible according to the received data.
Now I want to make all these stack panels to resources so I can reuse it in some new added tab controls and stack panels.
<StackPanel x:Name="ColorOption" Visibility="Collapsed">
<TextBlock Text="Line Color" Style="{StaticResource ItemNameTextBlockStyle}"/>
<Button Style="{StaticResource ColorButtonStyle}" Click="Color_Click">
<Button.Content>
<Rectangle x:Name="LineColorRect" Style="{StaticResource ColorSelectionRectangleStyle}" />
</Button.Content>
</Button>
</StackPanel>
Above is one example of stack panels I am using. In the code behind the function "Color_Click" will change this "ColorOption" stack panel state and do something.
However after I try to put this stack panel into Windows.Resources
<Window.Resources>
<StackPanel x:Name="ColorOption" Visibility="Collapsed" x:Key="ColorOption">
<TextBlock Text="Line Color" Style="{StaticResource ItemNameTextBlockStyle}"/>
<Button Style="{StaticResource ColorButtonStyle}" Click="Color_Click">
<Button.Content>
<Rectangle x:Name="LineColorRect" Style="{StaticResource ColorSelectionRectangleStyle}" />
</Button.Content>
</Button>
</StackPanel>
</Window.Resources> (I also put the style files inside)
In the tab controls I did
<TabControl>
<TabItem Header="Tab 1" Content="{StaticResource ColorOption}"/>
</TabControl>
The visual studio shows error in the code behind says "ColorOption does not exist in the current context"
How can I fix this? Is any way to set the context? thank you
You can simply wrap the StackPanel in ContentControl and make it ControlTemplate.
<ControlTemplate x:Key="ColorOptionTemplate" TargetType="{x:Type ContentControl}">
<StackPanel x:Name="ColorOption" Visibility="Collapsed">
<TextBlock Text="Line Color" Style="{StaticResource ItemNameTextBlockStyle}"/>
<Button Style="{StaticResource ColorButtonStyle}" Click="Color_Click">
<Button.Content>
<Rectangle x:Name="LineColorRect" Style="{StaticResource ColorSelectionRectangleStyle}"/>
</Button.Content>
</Button>
</StackPanel>
</ControlTemplate>
However, you will need to change properties of controls inside the ContentControl and it would be cumbersome. So the StackPanel could be wrapped in UserControl instead.
<UserControl x:Class="WpfApp1.ColorOptionControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel x:Name="ColorOption" Visibility="Collapsed">
<TextBlock Text="Line Color" Style="{StaticResource ItemNameTextBlockStyle}"/>
<Button Style="{StaticResource ColorButtonStyle}" Click="Color_Click">
<Button.Content>
<Rectangle x:Name="LineColorRect" Style="{StaticResource ColorSelectionRectangleStyle}"/>
</Button.Content>
</Button>
</StackPanel>
</UserControl>
This is a common way in WPF. The downside is that you will need to add dependency properties to UserControl and wire up them with dependency properties of internal controls so that you can set their values at the level of UserControl and bridge them with external controls and window. This could be complicated and cumbersome as well.
So I think ideally it would be better to find an existing control which has similar functionalities you want and create a custom control deriving from the existing one.

How To Make A WPF UserControl Act As A Container

I'm trying to create a Toolbar control that can group selected buttons with a border and a label. If there is already a built-in control that will do this then I could use that instead of building a UserControl.
If not, then what I'm wanting to build is a UserControl that would allow me to enter one-to-many of my ImageButton UserControls and set a GroupLabel text like below. Can this be done in WPF?
<User_Controls:ToolbarGroup GroupLabel="Entity">
<User_Controls:ImageButton ButtonText="Entity Setup"/>
<User_Controls:ImageButton ButtonText="New Entity"/>
</User_Controls:ToolbarGroup>
PS: I would post an image but this quirky forum won't allow me to post an image.
If i have got you correctly then I think you can achieve this way also, and on mouse eneter and leave event you can do the button click job.
for setting text you can use a grid and a label inside it to set the text, and Image buttons below it.
<UserControl x:Class="ABC.View.Oats"
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"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Image Source="{Binding Image}" Stretch="Fill"/>
</Grid>
</UserControl>
I think what you're looking for is a GroupBox, it has a header property where you can set the label.
Something like this:
<GroupBox Width="300" Height="100">
<GroupBox.Header>
<Label>Text</Label>
</GroupBox.Header>
<StackPanel>
<Button Content="Button"/>
<Button Content="Button"/>
<Button Content="Button"/>
</StackPanel>
</GroupBox>
I would also recommend using the groupbox, it seems to be doing exactly what you want it to do and it looks neat. Here's some examples on how to use them: http://www.dotnetperls.com/groupbox-wpf
On the other hand, if you believe the groupbox is not sufficient, you could create a control that inherits from the groupbox and you could extend it and add whatever you need to it. It would look like this:
public class customGroupBox: GroupBox{
....Add whatever you need here
}
Thanks for the replies. I tried the GroupBox and it's not the layout we want because we want the label underneath the buttons and centered. I never could find a way to add a collection to the UserControl. Maybe I didn't ask the question right by calling it a container. The code below will work, but it's not elegant. I wanted something that would wrap the layout in a UserControl and allow me to add a variable number of buttons to each toolbar group.
<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0">
<Border Background="GhostWhite" BorderBrush="Gainsboro" BorderThickness="1">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<User_Controls:ImageButton ButtonText="New 1"/>
<User_Controls:ImageButton ButtonText="New 2"/>
<User_Controls:ImageButton ButtonText="New 3"/>
</StackPanel>
<Label HorizontalAlignment="Center" Content="Group 1"/>
</StackPanel>
</Border>
<Border Background="GhostWhite" BorderBrush="Gainsboro" BorderThickness="1">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<User_Controls:ImageButton ButtonText="New 4"/>
</StackPanel>
<Label HorizontalAlignment="Center" Content="Group 2"/>
</StackPanel>
</Border>
</StackPanel>
One way to accomplish this is with a custom styled ItemsControl.
You can then reuse it and just bind it to different data.
Please forgive me, this is hand-typed...
In your resources...
<Style x:Key="ToolbarGroupItemsControlStyle" TargetType="ItemsControl">
...
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ItemsControl">
<Grid>
... XAML to form your group with a binding to the
... group name
<ItemsPresenter/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="ToolbarGroupItemTemplate">
<Grid>
... XAML and binding for each toolbar group item ...
</Grid>
</DataTemplate>
In your XAML...
<ItemsControl
Style="{DynamicResource ToolbarGroupItemsControlStyle}"
ItemsSource="{Binding ToolbarGroupItems}"
ItemTemplate="{DynamicResource ToolbarGroupItemTemplate"/>
If your resources above are at the application level, then you can place the ItemsControl above on any Window/UserControl you want.
Your ItemsSource will need to be a collection of a custom type you create that has bindings for the button text, etc.
I hope this is helpful.

Presenting an ItemsControl

simple question!
I want to present an itemscontrol inside of an expander and grid which contains a textbox. I want to do this multiple times so I wrapped it in a ControlTemplate.
<ControlTemplate x:Key="ArrayPresenter">
<Expander Template="{StaticResource ArrayTemplate}">
<Grid>
<ContentPresenter/>
<TextBlock FontWeight="Bold" Text="Empty" Margin="3" HorizontalAlignment="Center" Foreground="#66C9C9C9" FontSize="15" Visibility="{quickConverter:Binding '$P.Count == 0 ? Visibility.Visible : Visibility.Collapsed', P={Binding Array}}" />
</Grid>
</Expander>
</ControlTemplate>
This is what I want to present. Unfortunately whenever an item is added to the itemscontrol, nothing happens and it doens't display the new items!
<ContentControl Template="{StaticResource ArrayPresenter}">
<ItemsControl Style="{StaticResource ArrayItemsStyle}" Margin="5" ItemTemplate="{StaticResource StructureFieldTemplate}"/>
</ContentControl>
As mentioned in the comment you need to target type of your ControlTemplate
<ControlTemplate ... TargetType="{x:Type ContentControl}">
Without that ControlTemplate targets System.Windows.Controls.Control type and that does not have Content to present so ContentPresenter does not know what to show.

Layout navigation window

I would like to build a WPF window application using the following layout structure. Consider title and button on left hand frame/window like "Master Pages" in ASP.Net. On the right hand frame it should be a WPF navigation window.
When I include Navigation Window as an UI element at the last stack panel, it throws me and error. How should I design the entire layout according to the image screenshot below? Thanks
<Window x:Class="MainWindow"
xmlns:local="clr-namespace:ClientSocket"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title=" Desktop" Height="841" Width="1271" WindowStartupLocation="CenterScreen" WindowState="Maximized">
<DockPanel>
<StackPanel DockPanel.Dock ="Top" Orientation="Horizontal" Background="Red">
<TextBlock Background="red" FontSize ="36" Width="482" >
Main Title
</TextBlock>
</StackPanel>
<StackPanel Background="LightGray" DockPanel.Dock ="Left" Width="145">
<Button Content="Button1" Name="btnAndroid" Width="119" Margin="3" BorderBrush="{StaticResource {x:Static SystemColors.InfoBrushKey}}" />
<Button Content="Button2" Name="btnDownloads" Width="119" Margin="3" BorderBrush="{StaticResource {x:Static SystemColors.InfoBrushKey}}" />
<Button Content="AddNewDownloads" Height="37" Name="Button1" Width="133" />
</StackPanel>
<StackPanel>
<NavigationWindow Height="auto" Width="auto" Name="nwMain" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" BorderBrush="Blue" BorderThickness="1" />
</StackPanel>
</DockPanel>
</Window>
You cannot add a window as the child of anything, there is a nestable navigation control which you can use here instead, it is called Frame.
Layout-wise i would recommend a Grid with two rows, contains another Grid (in Grid.Row="1") with two columns.
DockPanels are sad controls that probably should not be used, unless someone points a gun at you and tells you to.

WPF Changing text in a controltemplate at run time

I am making a template control so that I can have a button with an image that changes when you click it. I also am trying to get text on top of the button that can change at run time. I have the button images and everything working but I can't seem to get that label at runtime so I can change the text. Here is the code in the xaml. I am missing the code behind
<UserControl.Resources>
<ControlTemplate TargetType="{x:Type Button}" x:Key="ActionButton">
<Grid>
<Label Panel.ZIndex="2" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Arial" Name="lblText" Foreground="#5E4421" FontWeight="Bold" FontSize="14">Test</Label>
<Image Name="Normal" Source="/AssaultWare.Controls;component/Replayer/Images/button_off.png"/>
<Image Name="Pressed" Source="/AssaultWare.Controls;component/Replayer/Images/button_on.png"/>
<Image Name="Disabled" Source="/AssaultWare.Controls;component/Replayer/Images/button_off.png" Visibility="Hidden"/>
</Grid>
<ControlTemplate.Triggers>
...
</ControlTemplate.Triggers>
</ControlTemplate>
</UserControl.Resources>
<Button Canvas.Left="471" Canvas.Top="465" Template="{StaticResource ActionButton}" Name="btnRight"/>
Difficult to decipher your question, but I think you just need to change the Label to a ContentControl and bind its Content property to the Button's Content property:
<ContentControl Content="{TemplateBinding Content}" .../>

Resources