I want to implement toolbox like control in WPF using User controls. I'm able to get the all Titles of UCITems and shown as tabs in UCTab and binded to StackPanel in UCTab using ContentProperty. But I need UCItem childrens also and bind to another stack panel in UCTab.
MainWindow.xaml:
<local:UCTab>
<local:UCItem Title="ToolBox 1">
<StackPanel>
<TextBlock Text="1"></TextBlock>
<TextBlock Text="2"></TextBlock>
<TextBlock Text="3"></TextBlock>
</StackPanel>
</local:UCItem>
<local:UCItem Title="ToolBox 2"></local:UCItem>
<local:UCItem Title="ToolBox 3"></local:UCItem>
</local:UCTab>`
UCTab UserControl
<UserControl x:Class="UserTab.UCTab "
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:UserTab"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Border Name="bd" Background="Gray" Panel.ZIndex="50" >
<StackPanel x:Name="host" >
</StackPanel>
</Border>
<Border x:Name="bdCanvas" Grid.Column="1">
<Canvas x:Name="canvas" Background="SkyBlue" >
<StackPanel x:Name="spPanel" Orientation="Vertical" Width="180" >
<Grid Background="Navy">
<Grid.ColumnDefinitions>
<ColumnDefinition ></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock x:Name="tbHeader" Foreground="White" Grid.Column="0" Text="Heading" Margin="3" ></TextBlock>
<Button x:Name="btnPin" Content="P" Margin="3" Grid.Column="1"></Button>
<Button x:Name="btnClose" Content="X" Margin="3" Grid.Column="2"></Button>
</Grid>
<StackPanel x:Name="panelUCItem" >
</StackPanel>
</StackPanel>
</Canvas>
</Border>
</Grid>
UCITem UserCotrol:
<UserControl x:Class="UserTab.UCITem "
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:UserTab"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<Style TargetType="{x:Type UCITem }">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type UCITem }">
<Border Name="Border"
Background="Gray"
Margin="5">
<Button x:Name="tbItem" Padding="5" Width="100" Height="28" Foreground="Black" Content="{Binding Title,UpdateSourceTrigger=PropertyChanged}">
<Button.LayoutTransform>
<RotateTransform Angle="90"></RotateTransform>
</Button.LayoutTransform>
</Button>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
On click of UCItem button, display UCItem content Stackpanel 'panelUCItem' in UCTab.
Help me how I can proceed with this structure. Thanks
Related
I'm trying to make a simple WPF app that has sections that fill the available width. Despite trying various ways of stretching the width of elements, containers, and children, nothing is working and I can't figure out why.
Another question said to use uniformgrid which worked well EXCEPT that it set the height of all the elements uniformly which was definitely not what I wanted. I want all of the sections to look like the one in the picture - filled width, height auto based on the content. Here's the basic setup:
<Window x:Class="A_Customizer.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:A_Customizer"
mc:Ignorable="d"
Title="MainWindow"
Background="#FF2B2B2B"
Width="800"
>
<Window.Resources>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type CheckBox}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid Name="mainApp" >
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<WrapPanel Grid.Row="0" >
<Button ToolTip="Click to apply the below settings to this Jumpbox" Click="ApplyCustomizations">Customize</Button>
</WrapPanel>
<ScrollViewer Grid.Row="1">
<WrapPanel HorizontalAlignment="Stretch" >
<GroupBox
Background="#FFE2E2E2"
BorderBrush="#FF7F7F7F"
Margin="10,10,10,10"
Name="pathsBox"
HorizontalContentAlignment="Stretch"
HorizontalAlignment="Stretch"
>
<GroupBox.Header>
<Border Background="#FFAFAFAF" CornerRadius="3">
<Label FontWeight="Bold">Key Paths</Label>
</Border>
</GroupBox.Header>
<StackPanel HorizontalAlignment="Stretch">
<Grid Margin="0,10,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<TextBox Name="homeFolder" Grid.Column="0" HorizontalAlignment="Stretch"></TextBox>
<Button Grid.Column="1" Click="NewQuickPath" ToolTip="Change home folder">
<Image Source="images\add_folder.png" Height="25" Cursor="Hand"></Image>
</Button>
</Grid>
<TextBox Name="progFolder" Grid.Column="0" HorizontalAlignment="Stretch"></TextBox>
</StackPanel>
</GroupBox>
<GroupBox
Background="#FFE2E2E2"
BorderBrush="#FF7F7F7F"
Margin="10,10,10,10"
Name="quickBox"
Height="auto"
HorizontalContentAlignment="Stretch"
>
<GroupBox.Header>
<Border Background="#FFAFAFAF" CornerRadius="3">
<Label FontWeight="Bold">Quick Access Folders</Label>
</Border>
</GroupBox.Header>
<StackPanel HorizontalAlignment="Stretch">
<TextBlock TextWrapping="Wrap" Margin="15">
There are going to be folders you'll need to access frequently and keeping them pinned on top of the left menu in Explorer is helpful.
Select here to add them to the list of folders restored with the "Customize" button. Click any folder to remove it.
</TextBlock>
<Border CornerRadius="3" Background="#FFF3C7C7" Margin="6" Visibility="Collapsed" Name="quickErr" Tag="err_box">
<TextBlock Tag="errMsg" Foreground="#FFFD3434" TextWrapping="Wrap" Margin="6" ></TextBlock>
</Border>
<UniformGrid Name="quickPathsArea" Columns="1">
</UniformGrid>
<Grid Margin="0,10,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" HorizontalAlignment="Stretch"></TextBox>
<Button Grid.Column="1" Click="NewQuickPath" ToolTip="Add a new folder">
<Image Source="images\add_folder.png" Height="25" Cursor="Hand"></Image>
</Button>
</Grid>
</StackPanel>
</GroupBox>
</wrappanel>
</scrollviewer>
</grid>
StackPanel with Orientation="Vertical" (default value) instead of WrapPanel should work: it will allow each child element use full width and as much height as necessary
I've an usercontrol with a groupbox where there's an itemscontrol in it.
Within the itemscontrol I put an scrollviewer.
When I run the application it isn't showing all the items.
Sometimes I see 1 or 2 items, sometimes nothing.
I'am certain that my list has at least 10 items in it.
What am I doing wrong here?
I've put the scrollviewer in the itemscontrol like described here:
WPF: ItemsControl with scrollbar (ScrollViewer)
<UserControl x:Class="Hermes.UI.HistoryListControl"
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:Hermes.UI"
mc:Ignorable="d"
d:DesignHeight="500" d:DesignWidth="800" d:DataContext="{x:Static local:HistoryListDesignModel.Instance}">
<GroupBox Margin="5 0"
Padding="4"
BorderBrush="{StaticResource clr_dark_brush}"
BorderThickness="0.5">
<GroupBox.Header>
<Label Content="Geschiedenis"
FontFamily="{StaticResource NunitoBold}"
FontSize="{StaticResource FontSizeRegular}"
Foreground="{StaticResource clr_dark_brush}"/>
</GroupBox.Header>
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer x:Name="ScrollViewer" Padding="{TemplateBinding Padding}">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:HistoryListItemControl />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</GroupBox>
</UserControl>
and hen the local:HistoryListItemControl
<UserControl x:Class="Hermes.UI.HistoryListItemControl"
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:Hermes.UI"
mc:Ignorable="d" d:DesignWidth="800">
<UserControl.Resources>
<Style x:Key="contentstyle" TargetType="{x:Type ContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<Border x:Name="background"
Background="White"
Margin="0 5">
<Grid x:Name="container" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding date_cal, StringFormat='dd MMMM yyyy'}"
FontSize="{StaticResource FontSizeLarge}"
FontFamily="{StaticResource NunitoThin}"
Foreground="{StaticResource clr_info_brush}"
VerticalAlignment="Center"
HorizontalAlignment="Center"/>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock FontFamily="{StaticResource FontAwesome}"
VerticalAlignment="Center"
Margin="5"
Text="" />
<TextBlock Text="{Binding Device_name}"
VerticalAlignment="Center"
Grid.Column="1"/>
<TextBlock FontFamily="{StaticResource FontAwesome}"
VerticalAlignment="Center"
Margin="5"
Text=""
Grid.Column="2"/>
<TextBlock Text="{Binding Unit_name}"
VerticalAlignment="Center"
Grid.Column="3"/>
</Grid>
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock FontFamily="{StaticResource FontAwesome}"
VerticalAlignment="Center"
Margin="5"
Text="" />
<TextBlock Text="{Binding Sensor}"
VerticalAlignment="Center"
Grid.Column="1"/>
<TextBlock FontFamily="{StaticResource FontAwesome}"
VerticalAlignment="Center"
Margin="5"
Text=""
Grid.Column="2"/>
<TextBlock Text="{Binding Battery}"
VerticalAlignment="Center"
Grid.Column="3"/>
</Grid>
<Grid Grid.Row="3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock FontFamily="{StaticResource FontAwesome}"
VerticalAlignment="Center"
Margin="5"
Text="" />
<TextBlock Text="{Binding Comments}"
VerticalAlignment="Center"
Grid.Column="1"/>
</Grid>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<ContentControl d:DataContext="{x:Static local:HistoryListItemDesignModel.Instance}"
Style="{StaticResource contentstyle}" />
</UserControl>
The items are loaded in with a viewmodel and is called from within the constructor of the viewmodel:
private void GetHistory()
{
HistoryBLL historyBLL = new HistoryBLL();
HistoryDataTable myHistory = historyBLL.GetHistoryByDeviceId(Device.Id);
foreach (HistoryRow row in myHistory)
{
UnitsBLL unitsBLL = new UnitsBLL();
Items.Add(new HistoryListItemViewModel
{
Date_cal = (DateTime)row.date_cal,
Device_name = row.tagnaam,
Unit_name = unitsBLL.GetUnitById(row.unit_id).unit,
Sensor = row.sensor_id.ToString(),
Battery = (row.battery) ? "Ja" : "",
Comments = row.comments
});
unitsBLL = null;
}
}
When I put a breakpoint at the last line I can see that the List of Items is filling up with at least 10 items, so that part is working.
I expect to see all the items and not just 1 or 2 (of even nothing)
The ListViewItems are getting their width from the TextBlock element. I want the ListViewItem to fit to the ListView. I have seen in other posts that making HorizontalContentAlignment="Stretch" will fix the issue, but my problem persists. The second TextBlock element in the ItemTemplate is set to WrapWithOverflow.
Sources:
http://www.teixeira-soft.com/bluescreen/2016/03/21/c-how-to-make-a-panel-within-a-datatemplate-fill-the-entire-width-of-a-listview-or-itenscontrol-derivative/
Code:
<UserControl x:Class="XXXX.Views.XXXXView"
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:cal="http://www.caliburnproject.org"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Background="{StaticResource BlackBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="32*"/>
<ColumnDefinition Width="6*"/>
<ColumnDefinition Width="32*"/>
</Grid.ColumnDefinitions>
<DockPanel Grid.Column="1">
<ListView Grid.Column="1"
x:Name="UniqueShortDescriptions"
VerticalAlignment="Stretch"
ItemsSource="{Binding UniqueShortDescriptions}"
SelectedItem="{Binding SelectedUniqueShortDescriptions}"
cal:Message.Attach="[Event SelectionChanged] = [Action SelectionChanged($this, $eventArgs)]">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Navy"
BorderThickness="3"
Margin="3"
Padding="2">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Grid.RowSpan="3"
Grid.Column="0"
Text="{Binding Path=Date}"
Foreground="Black"
VerticalAlignment="Center"
TextBlock.FontWeight="ExtraBold"/>
<TextBlock Grid.Row="0"
Grid.Column="1"
Text="{Binding Path=LongDescription}" Foreground="{StaticResource BlackBrush}"
TextWrapping="WrapWithOverflow"/>
<!--<TextBlock Text="{Binding Path=ShortExpenseDescription}" Foreground="{StaticResource BlackBrush}"/>-->
<TextBlock Grid.Row="1"
Grid.Column="1"
Text="{Binding Path=Cost}" Foreground="{StaticResource BlackBrush}"/>
<TextBlock Grid.Row="2"
Grid.Column="1"
Text="{Binding Path=Source}" Foreground="{StaticResource BlackBrush}"/>
</Grid>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</DockPanel>
</Grid>
</UserControl>
I got the code you posted to work by simply disabling horizontal scrolling of the ListView.
<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled" ...
I've found an solution of my problem.
Width=”{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=x:Type Expander}}, Path=ActualWidth}”
But I've got not correct width. (the width of the toggle button is not taken into consideration)
Is there any solutions in XAML for this?
<Page x:Class="Restore.Page1"
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:Restore"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Title="Page1">
<Grid Background="AliceBlue" HorizontalAlignment="Stretch">
<Expander Name="EXPANDER_NAME">
<Expander.Header>
<Grid Background="Red" Width="{Binding ElementName=EXPANDER_NAME, Path=ActualWidth}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<TextBlock Text="sdfsfsd" Grid.Column="0" />
<Button Content="OK" Grid.Column="1" />
</Grid>
</Expander.Header>
</Expander>
</Grid>
</Page>
I have the following user control:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="USER CONTROL" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" Name="label1"
VerticalAlignment="Top" FontSize="26" Padding="0"/>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
<Border BorderBrush="Black" BorderThickness="1">
<DockPanel x:Name="dPanel" Background="White">
</DockPanel>
</Border>
</ScrollViewer>
</Grid>
When I use the following XAML in my MainWindow.xaml:
<local:UserDockPanel>
<Label ...>
<Label ...>
</local:UserDockPanel>
It says I can't have more than one child.
My first question is: Should I be using a UserControl or should I use a Custom Control?
I thought UserControl would be best for my situation where I have a label, and Border and Scrollviewer over my DockPanel.
Also, From my understanding a Panel can't be templated. It is look-less and therefore has no style.
Second Question: If I should be using a UserControl, how can I make it so more than one child is allowed to be added into the dock panel?
You can do that with an ItemsControl, no need to subclass anything or create your own:
<Window x:Class="WpfApplication4.Window16"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window16" Height="300" Width="300">
<Window.Resources>
<Style TargetType="ItemsControl" x:Key="UserDockPanelStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ItemsControl">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="USER CONTROL" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" Name="label1"
VerticalAlignment="Top" FontSize="26" Padding="0"/>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
<Border BorderBrush="Black" BorderThickness="1">
<ItemsPresenter/>
</Border>
</ScrollViewer>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<DockPanel IsItemsHost="True" Background="White"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<ItemsControl Style="{StaticResource UserDockPanelStyle}">
<Label DockPanel.Dock="Bottom" Content="Bottom"/>
<Label DockPanel.Dock="Top" Content="Top"/>
<Border Background="Blue"/>
</ItemsControl>
</Window>