Use Binding for ElementName - c#

I was unable to find a solution for this problem:
I am creating my own table with ItemControls. To resize the columns I'd like to bind the Width-property of one cell to the corresponding ActualWidth-property of the column.
I tried the following, but it is not working:
<StackPanel Orientation="Vertical">
<Border BorderBrush="Black" BorderThickness="1">
<ItemsControl ItemsSource="{Binding Data.Columns}" Margin="26,1,1,1">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- here i set the name of the column (Code) -->
<Border BorderBrush="Black" BorderThickness="1,0,0,0" Width="100" x:Name="{Binding Code}">
<TextBlock Text="{Binding Header}" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
<ItemsControl ItemsSource="{Binding Data.Rows}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="1,0,1,1">
<StackPanel Orientation="Horizontal" Margin="1">
<Grid Width="25">
<General:SeverityIconControl Severity="{Binding Severity}" />
</Grid>
<ItemsControl ItemsSource="{Binding Values}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- and here i'd like to bind to the ActualWidth of the corresponding column (Code)
but it is not working because ElementName={Binding LocalCode} does not work -->
<Border BorderBrush="Black" BorderThickness="1,0,0,0" Width="{Binding ActualWidth, ElementName={Binding LocalCode}}">
<TextBlock Text="{Binding Value}" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
Is there a way to solve this without changing the data source (unfortunately the data source cannot be edited)?

You can't bind x:Name (more info here) since it's only read when you call InitializeComponent() in the constructor.
Easiest way would be to add a DesiredWidth column to your Data object, and bind both widths to that (with a default value of 100).

Related

How to Remove Spacing between ItemsControl Items

I have an ItemsControl with materialDesign Chips as a DataTemplate. My goal is to place the items one after the other without a lot of space in between.
There is a pic what is now looks like: https://imgur.com/hicWnGg.png
And this is my Goal: https://imgur.com/0jIEk8k.png
I tried already the ItemContainerStyle with Margin but this didnt helped me out
My Current Code
<ScrollViewer VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto">
<ItemsControl x:Name="myItemsControl" Height="40" Margin="0 10 0 0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="1"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<materialDesign:Chip Tag="{Binding Name}" Uid="{Binding SourceName}" Content="{Binding Code}" Width="75" IsDeletable="True" DeleteClick="Chip_DeleteClick"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
Change your ItemsPanelTemplate to StackPanel instead of UniformGrid
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>

WPF - ScrollViewer returns to start position

I have a table with cells, where values can be inserted. Table is generated dynamically, based on data. Table size is limited by the grid, where it is located. If data is too much, then appears a horizontal scroll bar.
This is implemented with ItemsControl in the ScrollViewer.
<ScrollViewer
VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding Data}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border>
<ItemsControl ItemsSource="{Binding Value}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition SharedSizeGroup="SomeCellRowSize"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="SomeCellRowSize"/>
</Grid.ColumnDefinitions>
<TextBox
Text="{Binding Value.TotalTime}"
HorizontalContentAlignment="Right" BorderThickness="0" Margin="1,1,0,0"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
The problem happens, when we scroll the table to the right and select some cell (TextBox). If we do this, then ScrollViewer will return to the most left position.
It's better to have an integrated ScrollViewer inside the ItemsPanel itself than wrapping a ScrollViewer around it. From my experience, you tend to have more issues. Update your Template to have the ScrollViewer instead.
<ItemsControl ItemsSource="{Binding Data}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}"/>
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border>
<ItemsControl ItemsSource="{Binding Value}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition SharedSizeGroup="SomeCellRowSize"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="SomeCellRowSize"/>
</Grid.ColumnDefinitions>
<TextBox
Text="{Binding Value.TotalTime}"
HorizontalContentAlignment="Right" BorderThickness="0" Margin="1,1,0,0"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

Bind to item in collection, code behind

I want to bind to a specific item of my itemsControl (named maskDataBinding). I tried this:
<VisualBrush Visual="{Binding ElementName=maskDataBinding,Path=[0]}"/>
but it doesnt work. Also, could I bind the index as well? I have a slider and would like to update the item it is binded to when I adjust the slider.
Something like this:
<VisualBrush Visual="{Binding ElementName=maskDataBinding,Path=[{Binding ElementName=ScaleXSlider, Path=Value]}"/>
Edit:
Here is maskDataBinding simplified
<!--Outer collection-->
<ItemsControl Name="maskDataBinding">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Transparent"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!--nested collection-->
<ItemsControl Background="Transparent" ItemsSource="{Binding ImageSource}>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Transparent"</Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Source="{Binding Name}"</Image>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

Using ItemsControl to bind buttons top/left position on canvas Windows Phone

I am using ItemsControl and have several buttons and place them at a specific location on the canvas. However, the Canvas.Left and Canvas.Top always place all buttons at 0,0.
<ItemsControl x:Name="itemsControl" ItemsSource="{Binding Tiles}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Width="{Binding Side}"
Height="{Binding Side}"
Background="{Binding BgColor}"
Canvas.Left="{Binding Left}" Canvas.Top="{Binding Top}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The best answer I've found for this is to use a RenderTransform in your datatemplate
<ItemsControl x:Name="itemsControl" ItemsSource="{Binding Tiles}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Width="{Binding Side}" Height="{Binding Side}" Background="{Binding BgColor}">
<Button.RenderTransform>
<TranslateTransform X={Binding Left} Y ={Binding Top}/>
</Button.RenderTransform>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

How do I dynamically size a GridView Item?

I have a Grid View that is used to display "tags" which is a list of strings that are dynamic in size. Using the following code:
<GridView ItemsSource="{Binding Tags}"
ItemTemplate="{StaticResource TagTemplate}"
VerticalAlignment="Bottom"
Grid.RowSpan="2"
SelectionMode="None"
/>
I use the following Template for the items:
<DataTemplate x:Name="TagTemplate">
<Border BorderBrush="Gray" BorderThickness="1" Opacity="75">
<TextBlock Text="{Binding}"/>
</Border>
</DataTemplate>
When added to the Grid, the size of each of the items are the same size as the first:
How do I dynamically size the items within the GridView?
So something like;
<ScrollViewer>
<ItemsControl ItemsSource="{Binding Tags}">
<!-- ItemsPanelTemplate -->
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
<!-- Or use WrapPanel depending on its display -->
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<!-- ItemContainerStyle -->
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Gray" BorderThickness="1" Opacity="75" Padding="3" Margin="3,0">
<TextBlock Text="{Binding}"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>

Categories

Resources