Horizontally centered horizontal ItemsControl - c#

How can I create horizontally oriented ItemsControl, where items are aligned the same way how these two labels are aligned in this Grid?
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Column="1">Text 1</Label>
<Label Grid.Column="3">Text 2</Label>
</Grid>
I already have a View for the items, so using ItemsTemplate is probably not an option.
Resources
Here are some tutorials and articles about creating your own custom panel. Hope this will help someone with similar problem...
UniformGrid for Silverlight
Animate WPF Datatemplate when item added to Listbox?
Creating Custom Panels In WPF
FishEyePanel/FanPanel - Examples of custom layout panels in WPF
WPF - A Constraining Stack Panel

About the closest you could get without writing your own panel would be:
<ItemsControl ItemsSource="{Binding TheItems}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="1"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Control.HorizontalAlignment" Value="Center"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
Note that I'm .NET-less at the moment so cannot test the above.

Related

MaterialDesignThemes ComboBox Selected Item template issue

I'm working on styling a WPF ComboBox so that the ComboBoxItems have some additional data. The items look great when in the drop down, but once selected, the displayed item is not stretched/filling the ComboBox- it's all smushed to the left. I've done enough digging to figure out this is related to the MaterialDesign Theme being applied to the control. Without MeterialDesign being referenced in a demo project, the code works as anticipated.
<ComboBox Width="150"
Margin="2"
HorizontalContentAlignment="Stretch" <!-- No Effect //-->
materialDesign:HintAssist.Hint="Select Item"
ItemsSource="{StaticResource ExampleItems}" >
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding DisplayText}" />
<Ellipse Grid.Column="1" Width="10" Height="10" Fill="{Binding Color}"/>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
<!-- No Effect //-->
<!--<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem" BasedOn="{StaticResource MaterialDesignComboBoxItemStyle}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ComboBox.ItemContainerStyle>-->
</ComboBox>
I've tried pretty much everything I can without luck- Including various controls inside the DataTemplate, stack panel, dock panel, etc....
I've created a minimum reproducible example here: ComboBoxDemo Project
I've included the ComboBox Style I pulled from Blend, to try to dig into what MaterialDesign is doing on top of the normal template. I see that there is an ItemContainerStyle for the selected item, but it looks like it's binding the HorizontialContentAlignment up the chain. Manually setting that to Stretch did not help.
So Hopefully a Xaml guru out there can pinpoint the issue...

WPF container with fix size children

I want a container that have 3 columns and in each column, the cell can wrap it's content like the picture below
So far, I've done this:
<ListBox Name="listQuestion">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="3"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
But the result is every cell have the same size as the biggest cell.
If you want to have a grid with three separate lists as their columns you should be able to use a combination of a Grid and a listbox
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListBox Grid.Column="0"/>
<ListBox Grid.Column="1"/>
<ListBox Grid.Column="2"/>
</Grid>
A grid will give you the most flexibility in your layout and allows you to have elements span multiple columns or rows. If you don't need all that flexibility you could use a stackpanel instead
<StackPanel Orientation="Horizonal">
<ListBox/>
<ListBox/>
<ListBox/>
</StackPanel>

WPF Changing column width at runtime

I have an WPF application that contains a grid. The grid is split into 3 columns with the 3rd grid having zero width upon loading.
I have two datagrids in the other two columns. When the selected item in one of the datagrid changes the other datagrid changes it display values, i.e. a master detail template. This all works fine.
There is one value in the datagrid that if selected I wish this 3rd column to changes its width from zero to 2*. I don't know how to do this?
EDIT
I wish to achieve this through XAML. I have been looking at data triggers & value converters. I written some code below quickly to test. I have read that setting the column to width=0 there is probably higher on the dependency property setting precedence list. Is there anyway to do this or will I need to use code behind?
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="0"/>
</Grid.ColumnDefinitions>
<DataGrid Grid.Column="0"
ItemsSource="{Binding OrderList}"
SelectedItem="{Binding OrderSelected}"
AutoGenerateColumns="True">
</DataGrid>
<TextBox Grid.Column="1" Text="{Binding OrderSelected.Name}">
</TextBox>
<Grid x:Name="columnHideSeek" Grid.Column="2" Background="Blue">
<Grid.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding OrderSelected.Name}" Value="Mark">
<Setter Property="Grid.Width" Value="10"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
</Grid>
Your XAML file should looks like this:
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition Name="thirdColumn" Width="0"/>
</Grid.ColumnDefinitions>
</Grid>
And selected datagrid event scope in your code behind file:
GridLength g2 = new GridLength(2, GridUnitType.Star);
thirdColumn.Width = g2;

WinRT ItemsControl with Grid columns and rows

I'm new to XAML. I searched about ItemsControl and I found a tutorial, which is easy to understand, but the problem is that it is not work in WinRT.
Tutorial: https://rachel53461.wordpress.com/2011/09/17/wpf-itemscontrol-example/
I tried to use TargetType in Style tag, however, in runtime I got an exception.
<ItemsControl ItemsSource="{Binding MyCollection}">
<!-- ItemsPanelTemplate -->
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<!-- ItemContainerStyle -->
<ItemsControl.ItemContainerStyle>
<Style TargetType="TextBox">
<Setter Property="Grid.Column"
Value="{Binding xIndex}" />
<Setter Property="Grid.Row"
Value="{Binding yIndex}" />
</Style>
</ItemsControl.ItemContainerStyle>
<!-- ItemTemplate -->
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Background="{Binding color}" Text="{Binding xIndex,Mode=OneWay}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Your problem is here:
<Style TargetType="TextBox">
this is what is should be:
<Style TargetType="ContentPresenter">
The ItemContainer for an ItemsControl is a ContentPresenter (unless a specific item is added to the ItemsControl).
So your view hierarchy looks something like this (assuming you didn't change the ItemsPanel to something other than a StackPanel):
<StackPanel>
<ContentPresenter>
<TextBox/>
</ContentPresenter>
</StackPanel>
Edit:
As Scott pointed out in the comments, this solution doesn't actually work for WinRT. I did something similar and you can probably modify it to do the appropriate binding:
public class CustomItemsControl : ItemsControl
{
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
base.PrepareContainerForItemOverride(element, item);
FrameworkElement source = element as FrameworkElement;
if (source != null)
{
source.SetBinding(Canvas.LeftProperty, new Binding { Path = new PropertyPath("X"), Mode = BindingMode.TwoWay });
source.SetBinding(Canvas.TopProperty, new Binding { Path = new PropertyPath("Y"), Mode = BindingMode.TwoWay });
}
}
}
This binds the Canvas.LeftProperty to the X property on each item in the collection and similarly the Canvas.TopProperty and the Y property.

is there a datatemplate for grid panel elements in WPF?

Fairly new to WPF...
I have a collection of data I would like to bind to a grid panel. Each object contains its grid row and column, as well as stuff to fill in at the grid location. I really like how I can create data templates in the listbox XAML to create a UI with almost nothing in the code behind for it. Is there a way to create a data template for grid panel elements, and bind the panel to a data collection?
You can use an ItemsControl with a Grid as its panel. Here is an example. XAML:
<ItemsControl x:Name="myItems">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding MyText}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<Style.Setters>
<Setter Property="Grid.Row" Value="{Binding MyRow}" />
<Setter Property="Grid.Column" Value="{Binding MyColumn}" />
</Style.Setters>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
Codebehind (for testing purposes):
public Window1()
{
InitializeComponent();
myItems.ItemsSource = new[] {
new {MyRow = 0, MyColumn = 0, MyText="top left"},
new {MyRow = 1, MyColumn = 1, MyText="middle"},
new {MyRow = 2, MyColumn = 2, MyText="bottom right"}
};
}
Not sure if this will help you, but why don't you try setting the ItemsPanel of an ItemsControl (ListBox, ListView) to a UniformGrid. Something like this:
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
It's similar to the previous solution, only a little more dynamic.

Categories

Resources