Reputation: 902
I developed last week an Application A
that had a "wide" MainWaindow (more than 1400 pixels)
I am at the present time starting the development of a new Application B (which looks for running Excel instances)
So I have a view that contains a DataGrid which has its Width
property to Auto
(Designer picture below). Everything's fine
Then I insert it to the MainWindow (here Designer picture)
It is not what exactly what I expected but I still have to make some research in SO questions like this one wpf-datagrid-why-the-extra-column (the answer tells it is not an extra column it is a supplementary width...)
Then I run this Application B
. Wonder: I get an even wider window.
The exact question I want to expose here is:
B
the same width as the one of last week's Application A
?I do not believe in coincidence (I did also no copy/paste between the 2 applications). Where is it back-up ? I already read posts about styles (default style, style dedicated to window not applied to the inheriting MainWindow ... )
Any (real) rationale reading about WPF also welcome !
EDIT: Add code (I first did not wanted to show code to concentrate on the question. Because there are "thousand" places where you can set a Width... with effect or not)
<UserControl ...
d:DataContext="{d:DesignInstance {x:Type vm_nmspc:MainWindowVm}, IsDesignTimeCreatable=True}">
<UserControl.Resources>
<Style TargetType="DataGridRow">
<Setter Property="Width" Value="Auto"/>
...
</Style>
</UserControl.Resources>
<Grid>
<DataGrid ItemsSource="{Binding OpenExcelColl}" AutoGenerateColumns="False" AlternationCount="{Binding OpenExcelColl.Count}"
VirtualizingPanel.IsVirtualizing="False" CanUserAddRows="False" SelectedItem="{Binding SelectedExcelObject}">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" IsReadOnly="True"/>
<DataGridTextColumn Header="Path" Binding="{Binding CompletePath}" IsReadOnly="True"/>
<DataGridTextColumn Header="Type" Binding="{Binding ExtType}" IsReadOnly="True"/>
</DataGrid.Columns>
...
</DataGrid>
</Grid>
</UserControl>
And the MainWindow.xaml (Note that no Width had been given, hoping that the MainWindow would fit automatically. Width="Auto"
did not work)
<Window ...
DataContext="{DynamicResource ResourceKey=MyVM}"
mc:Ignorable="d"
Title="MainWindow" Height="350"
SizeToContent="Width"> <<------- Line added to "workaround/solve" the problem
<Window.Resources>
<vm_nmspc:MainWindowVm x:Key="MyVM"/>
</Window.Resources>
<Grid>
<views:AllExcelObjDataGrid DataContext="{Binding}"/>
</Grid>
</Window>
After SizeToContent="Width"
Upvotes: 0
Views: 80
Reputation: 170
The problem here is that you set width to auto, meaning it will take all available space from its parent.
If I look up the visual tree no other width has been set, so your datagrid will stretch over the entire application.
The reason application B takes the exact same space in debugging as application A is because Windows actually thinks these are the same applications because they are started both with vshost.
Now, you can set your width on the parent, I prefer something like this:
<Window...
Width="1366"
MinWidth="{Binding Source={x:Static SystemParameters.FullPrimaryScreenWidth}, Converter={StaticResource ScreenSizeConverter}}"
your datagrid will still stretch over the entire application, remove the width=auto setter if you want to create space on the left or right to place some extra controls.
Now, either apply a static width to your datagrid or use the Grid you wrap your datagrid in and divide in columns using a dynamic width. example:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<DataGrid Grid.Column="0" ItemsSource="{Binding OpenExcelColl}" AutoGenerateColumns="False" AlternationCount="{Binding OpenExcelColl.Count}"
VirtualizingPanel.IsVirtualizing="False" CanUserAddRows="False" SelectedItem="{Binding SelectedExcelObject}">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" IsReadOnly="True"/>
<DataGridTextColumn Header="Path" Binding="{Binding CompletePath}" IsReadOnly="True"/>
<DataGridTextColumn Header="Type" Binding="{Binding ExtType}" IsReadOnly="True"/>
</DataGrid.Columns>
...
</DataGrid>
<StackPanel Grid.Column="1">
<!-- Additional controls here -->
</StackPanel>
</Grid>
if you still have a little white space you want to get rid off use
<DataGrid ColumnWidth="*" ...
This will divide remaining space among your columns.
EDIT
You do not really need the sreensizeconverter, you can set a static number, it is a quick and dirty implementation to set the parent window minwidth, for your convenience:
public class ScreenSizeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value.GetType() == typeof(double))
{
return (((double)value / 4) * 3);
}
else
{
return null;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
in App.xaml (Window.Resources should work but I think you are forgetting ResourceDictionary, that is why it won't compile, I prefer App.xaml because now you only need to import it once and you use across all windows and usercontrols):
<Application x:Class="MecamApplication.Client.App"
...
xmlns:Converters="clr-namespace:MecamApplication.Core.Converters;assembly=MecamApplication.Core">
<Application.Resources>
<ResourceDictionary>
<Converters:ScreenSizeConverter x:Key="ScreenSizeConverter"/>
</ResourceDictionary>
</Application.Resources>
Still, you could just set minwidth="500" and width="950" and you would achieve the same, I forgot to clean that part out.
Upvotes: 2