My WPF UserControl must never get wider than the containing ButtonBar - wpf

I have bound at top the Width of the UserControl to the Width of the ButtonGrid at top.
It does not work. I want my UserControl always that wide as the width of the ButtonGrid. The problem is loading documents with a long name > Sum(Width of 3 buttons) makes the UserControl as wide as the document name. Now imagine having document names with 100 chars or longer and you add documents the UserContol will bump and jump...
<UserControl x:Class="TBM.View.DocumentListView"
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:Behaviours="clr-namespace:FunctionalFun.UI.Behaviours"
xmlns:Helper="clr-namespace:TBM.Helper"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300"
Width="{Binding ElementName=ButtonGrid,Path=Width}"
>
<UserControl.Resources>
<Helper:BooleanToVisibilityConverter x:Key="boolToVisibilityConverter" />
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListBox
SelectionMode="Extended"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling"
Behaviours:MultiSelectorBehaviours.SynchronizedSelectedItems="{Binding SelectedDocumentViewModelList,Mode=TwoWay}"
Width="Auto"
Focusable="True"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
Grid.Row="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Name="documentListBox"
BorderThickness="1"
ItemsSource="{Binding DocumentList}"
Visibility="{Binding ElementName=documentListBox,Path=HasItems, Converter={StaticResource boolToVisibilityConverter}}"
>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<!--<TextBlock Text="{Binding Path=Id}" />-->
<TextBlock Text="{Binding Path=DocumentName}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<UniformGrid x:Name="ButtonGrid"
Grid.Row="1"
Rows="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
>
<Button Command="{Binding Path=DeleteDocumentCommand}" HorizontalAlignment="Stretch" Content="Delete" />
<Button Command="{Binding Path=AddDocumentCommand}" HorizontalAlignment="Stretch" Content="Add" />
<Button Command="{Binding Path=OpenDocumentCommand}" HorizontalAlignment="Stretch" Content="Open" />
</UniformGrid>
</Grid>
</UserControl>

You could also set the width of the ParentGrid(containing the control) to a fixed size, en then horizontal alignment to Stretch

Try 2 stuff
Use horizontal alignment on user control to stretch
Set binding to MaxWidth same as Width binding

Related

How to fix Binding TextBlock in WPF MVVM?

You see my XAML code at the bottom; when I debug it in the runtime, I see nothing in two TextBlocks of the StackPanel of my window, whereas there is some data in the binding TextBlocks when it is running!
Why can I see nothing in those TextBlocks?
<Grid Name="SchoolGridView"
AutomationProperties.AutomationId="SchoolGridView"
AutomationProperties.Name="School Group" >
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<ListView Grid.Row="0" Height="Auto" x:Name="List"
HorizontalContentAlignment="Center" ItemsSource="{Binding
PeopleList}" SelectionMode="Single">
...
</ListView>
<StackPanel Background="LightGray" Height="60"
Orientation="Horizontal" VerticalAlignment="Bottom" Grid.Row="1"
Visibility="{Binding
IsDetailVisible,UpdateSourceTrigger=PropertyChanged}">
<StackPanel HorizontalAlignment="Left" Width="320">
<TextBlock Height="20" Text="asaasdasd"></TextBlock>
<TextBlock Height="20" HorizontalAlignment="Left"
Background="Yellow" Text="{Binding DataContext.FullName,
UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Height="20" HorizontalAlignment="Left"
Background="Yellow" Text="{Binding
DataContext.RowSelectedItem,
UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
<WrapPanel HorizontalAlignment="Right">
<Button Content="DELETE" HorizontalAlignment="Right"
VerticalAlignment="Top"
Width="auto" Height="50" Margin="3" Command="
{Binding DataContext.DeleteCommand, ElementName=List}"
CommandParameter="{Binding SelectedItem,
ElementName=List}"/>
</WrapPanel>
</StackPanel>
</Grid>
</Window>
You must fill DataContext
<Window x:Class="SampleApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SampleApplication"
Title="MainWindow" Height="350" Width="525">
Or set it in Code
DataContext = new ViewModel();

Textbox does not show a verticalscrollbar

<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"
mc:Ignorable="d" x:Class="WpfApplication1.MainWindow"
Title="MainWindow" Height="350" Width="550" MinHeight="350">
<DockPanel Background="BlanchedAlmond">
<DataGrid Background="YellowGreen" DockPanel.Dock="Top" MinHeight="100">
</DataGrid>
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" FlowDirection="RightToLeft" Margin="10" Background="YellowGreen">
<Button HorizontalAlignment="Right" Click="Button1Add_Click" Margin="5,0">Add text 1</Button>
<Button HorizontalAlignment="Right" Click="Button2Add_Click">Add text 2</Button>
<Button HorizontalAlignment="Right" Click="Button1_Click" Margin="5,0">Toggle textbox 1</Button>
<Button HorizontalAlignment="Right" Click="Button2_Click">Toggle textbox 2</Button>
</StackPanel>
<Grid Background="Red">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBox x:Name="TextBox1" Grid.Row="0" Background="AliceBlue" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">Test 1</TextBox>
<TextBox x:Name="TextBox2" Grid.Row="1" Background="AliceBlue" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">Test 2</TextBox>
</Grid>
</DockPanel>
</Window>
In the example above I am trying to achieve that the two textboxes in the middle just fill the available space between the top datagrid and the bottom stackpanel with buttons.
They have to divide that space between them depending on their text-content and their visibility.
Both properties can change by databindings, I simulated that with the click events.
But when the space is filled up they have to show a vertical scrollbar when needed.
The code sample above is not good. When I add text to a textbox, the grid-row becomes larger but disappears from the visible region, no scroll bar.
EDIT: I ended up with:
<ScrollViewer Background="AliceBlue" VerticalScrollBarVisibility="Auto">
<StackPanel Orientation="Vertical">
<Label x:Name="Label1" Margin="0,6,0,0">Test 1:</Label>
<TextBox x:Name="TextBox1" Padding="0,6"></TextBox>
<Label x:Name="Label2" Margin="0,6,0,0">Test 2:</Label>
<TextBox x:Name="TextBox2" Padding="0,6" ></TextBox>
</StackPanel>
</ScrollViewer>
You need to add a ScrollViewer in your XAML around the content.
ScrollViewer on MSDN
<ScrollViewer>
Content
</ScrollViewer>

WPF height and scroll at listbox - imposible

To keep things simple all i am trying to do is to place a listbox and a button below it. Although it seems simple it isn't. It is not, because it is in a GRID...
The row size is star size and listbox having verticalAlign top works great all the time. The problem is that I cannot add a button below it. Having a grid with 2 rows one star height and the other auto would place the button at the bottom of the form even if listbox contents are little. Trying to set both rows auto doesn't work when resizing as no scrollbar is visible at the listbox.... Any workaround for this??
Update some code
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<DockPanel >
<ListBox DockPanel.Dock="Top" Name="lbStaff" ItemsSource="{Binding}"
Grid.Row="0" VerticalAlignment="Top" BorderThickness="0"
Background="WhiteSmoke" Margin="15,10,20,30" Style="{DynamicResource
ListBoxUsers}" ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource
ListBoxTest1}"></Style>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate >
<StackPanel Margin="5,4,5,4">
<TextBlock HorizontalAlignment="Stretch" FontSize="16"><Run
Text="{Binding Name}"/> - <Run Text="{Binding Mode=OneWay,
Path=PositionString}"/></TextBlock>
<TextBlock >Τηλέφωνο <Run Text="{Binding Phone}"/>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button DockPanel.Dock="Top" Grid.Row="0" HorizontalAlignment="Right"
VerticalAlignment="Top" Margin="0,10,7,0" Style="{DynamicResource
ButtonStyleNew1}">
<Button.Content>
<StackPanel Orientation="Horizontal">
<Image Source="/WpfApplication1;component/Images/filenew1.png"
Stretch="None" VerticalAlignment="Center"></Image>
<TextBlock Margin="5,0,0,0" FontSize="16">Προσθήκη Χρήστη</TextBlock>
</StackPanel>
</Button.Content>
</Button>
</DockPanel>
</Grid>
</Grid>
What i usually do is not using rows of grid but using DockPanel you can adjust the alignments by nesting each elements. But again it totally depends on the designer how they design that using grid row or any other way. What i got from the question the following code should help you out.
but if you post some code then we can figure out where the actual problem is.
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<DockPanel>
<DockPanel DockPanel.Dock="Top">
<ListBox Height="50"/>
</DockPanel>
<DockPanel DockPanel.Dock="Bottom">
<Button Height="20" DockPanel.Dock="Top"/>
<Label/>
</DockPanel>
</DockPanel>
</Grid>
So your problem here is that you have the in the ListBox you have ScrollViewer.VerticalScrollbars=Visible that make it collapsed if you dont want scrollbars and i would suggest not to use margins more in the designing. if you still have scroll bars remove the height of the ListBox and make the window larger. It all depends upon the size of the window if you don't have the size and proper alignment. Refining your code
<Window xmlns:my="clr-
namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input.Toolkit"
x:Class="MyLightWpfApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
xmlns:local="clr-namespace:MyLightWpfApplication.ViewModel"
DataContext="{Binding Main, Source={StaticResource Locator}}">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Skins/MainSkin.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<DockPanel >
<DockPanel DockPanel.Dock="Top" Width="400" Height="200">
<ScrollViewer DockPanel.Dock="Top" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<ListBox Name="lbStaff" ItemsSource="{Binding AutoCompleteData}"
BorderThickness="0"
Background="WhiteSmoke" >
<ListBox.ItemTemplate>
<DataTemplate >
<StackPanel >
<TextBlock HorizontalAlignment="Stretch" FontSize="16"><Run
Text="{Binding FirstName}"/> - <Run Text="{Binding Mode=OneWay,
Path=PositionString}"/></TextBlock>
<TextBlock >Τηλέφωνο <Run Text="{Binding LastName}"/>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
</DockPanel>
<DockPanel DockPanel.Dock="Bottom">
<Button DockPanel.Dock="Top" Height="30" Grid.Row="0">
<Button.Content>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="16">Προσθήκη Χρήστη</TextBlock>
</StackPanel>
</Button.Content>
</Button>
<Label/>
</DockPanel>
</DockPanel>
</Grid>
</Window>
Its all dependent on how much data you have in the ListBox. I have tried this code populating listbox with 20 rows its not showing scrollbars at all
You might try auto for both and put a MaxHeight on the ListBox but you still take a chance of pushing the button off the screen. Or put both in a ScrollViewer. Or can you live with the button on top?
I solved this problem using a dockpanel. I docked buttons at bottom and then i let listbox to fill the remaining area..(lastchildfill=true) ...
It works fine...

Wpf ItemsControl with datatemplate, problem with doubled border for some items

I have simple ItemsControl with custom datatemplate, template contains only textblock with border. All items should be displayed vertically one after another, but some items have extra border.
How can I remove it?
I want to achieve something similar to enso launcher, it looks like
My implementation looks like this
here is my xaml code:
<Window x:Class="winmole.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
x:Name="hostWindow"
Height="Auto"
MinHeight="100"
MinWidth="100"
Width="Auto"
Padding="10"
AllowsTransparency="True" WindowStyle="None" Background="Transparent"
Top="0"
Left="0"
SizeToContent="WidthAndHeight"
Topmost="True"
Loaded="Window_Loaded"
KeyUp="Window_KeyUp"
>
<Window.Resources>
<!--Simple data template for Items-->
<DataTemplate x:Key="itemsTemplate">
<Border Background="Black" Opacity="0.9" HorizontalAlignment="Left" CornerRadius="0,2,2,0">
<TextBlock Text="{Binding Path=Title}"
TextWrapping="Wrap"
FontFamily="Georgia" FontSize="30"
Height="Auto"
HorizontalAlignment="Left"
VerticalAlignment="Stretch"
TextAlignment="Left" Padding="5" Margin="0" Foreground="Yellow"/>
</Border>
</DataTemplate>
</Window.Resources>
<DockPanel>
<ItemsControl DockPanel.Dock="Bottom" Name="itcPrompt"
ItemsSource="{Binding ElementName=hostWindow, Path=DataItems}"
ItemTemplate="{StaticResource itemsTemplate}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</DockPanel>
If I understand your question correctly: Try to set SnapsToDevicePixels="True" on the Border
<Border SnapsToDevicePixels="True" Background="Black" Opacity="0.9" ...

How to set WPF ScrollViewer height dynamically?

I have the following test sample:
<Window x:Class="WpfScrollTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="200" Width="200">
<Border>
<StackPanel>
<Label Width="Auto" Height="Auto" Content="Text to mess up the scrollview"/>
<ScrollViewer Height="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Border}}, Path=ActualHeight}">
<StackPanel>
<Button MinWidth="100" MinHeight="100" Content="Button"/>
<Button MinWidth="100" MinHeight="100" Content="Button"/>
</StackPanel>
</ScrollViewer>
</StackPanel>
</Border>
</Window>
Which creates this:
My question is how do I set the ScrollViewer.Height dynamically while still being able to see the bottom of the scrollbar? In my sample, the Height of the ScrollViewer is too long because of the Label above it ..
I don't want to fix the Height of the ScrollViewerto a static value.
I would recommend to remove the outer StackPanel to a Grid, since Stackpanel wont respect the children size. And remove the ScrollViewer.Height binding. Now you just need to create two RowDefinition for the Grid and place the Label to Grid.Row=0 and ScrollViwer to Grid.Row=1.
Code is below. So my tip here is, use StackPanel/Canvas only if necessary and may be for the inner levels. Try to use Grid more to get very dynamic layouts.
<Border>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Width="Auto" Height="Auto" Content="Text to mess up the scrollview"/>
<ScrollViewer Grid.Row="1" >
<StackPanel>
<Button MinWidth="100" MinHeight="100" Content="Button"/>
<Button MinWidth="100" MinHeight="100" Content="Button"/>
</StackPanel>
</ScrollViewer>
</Grid>
</Border>

Resources