WPF Data Binding - Bind to UI Control from a Template - wpf

I have a template in my section. I want to bind the Width of one of the values in that template to the width of a control in my Main XAML section.
Can this be done? Expression Blend only shows the Template in the Binding list.
For example, this is what I am wanting to have work:
<Windows.Resources>
... My template stuff
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="{Binding ElementName=SecondColumn, Path=Width}"/>
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
... More template stuff
</Windwos.Resources>
<Grid Name="MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Name="FirstColumn" Width=".25*" />
<ColumnDefinition Name="SecondColumn" Width=".5*" />
<ColumnDefinition Name="ThirdColumn" Width=".25*" />
</Grid.ColumnDefinitions>
... Rest of my XAML

Once inside the Template you're sort of isolated from other elements (with good reason - it can be reused elsewhere). In this case (assuming the template is used somewhere under "MainGrid") it looks like you can use a RelativeSource FindAncestor Binding to locate the parent Grid (you'll need to make sure to count the Grids in the VisualTree to get the right AncestorLevel - in just the code here it would be 2). The Path would be ColumnDefinitions[1].Width. Keep in mind that this depends on you maintaining the structure of the elements where you are using the template so it is a bit fragile. There is also an alternate method using SharedSizeGroup that can connect Grid Rows or Columns at different levels but that works only with Auto and fixed pixel sizes. This Binding method works with fixed and * sizes.
Entire Binding:
Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Grid}, AncestorLevel=2}, Path=ColumnDefinitions[1].Width}"

Do you mean that you want your columns to be always the same width or do you mean that at first, they are at same width? If so, why not define a style and use it from both columns?

Related

WPF: ColumnSpan in UniformGrid

I know that UniformGrid haven't attached properties ColumnSpan and RowSpan. But what i really need is container with fixed width and inner cells also with fixed widths, except few UIElements, that should be filled in few cells.
For example:
<UniformGrid Columns="4"> <TextBlock>1</TextBlock>
<TextBlock>2</TextBlock>
<TextBlock Grid.ColumnSpan="2">34</TextBlock>
UniformGrid is ideal for me except this situation: last TextBlock is not fill two cells.
Is it possible use some other solution to give the needed result?
Thank you for any advise!
P.S.And... why XAML parser is not stops with error where process this markup?
You could use a Grid with the columns having varying * widths:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<TextBlock>1</TextBlock>
<TextBlock Grid.Column="1">2</TextBlock>
<TextBlock Grid.Column="2">34</TextBlock>
</Grid>
I wanted use only XAML, but for now I still not found the answer. So, i've used following solution: placed all my elements in horizontal WrapPanel and set width for each element in code.

In WPF Style in XAML, possible to declare to a control "Your width is 50 percent of available width"

I have seen offhand comparisons of WPF to web development in remarks such as (I paraphrase) "web developers will find the WPF style paradigm familiar". Is it possble to specify control sizes as percentages of their container's dimension? If so, in WPF XAML , how would one tell a control to take 50% of its container's width even if the container's width changes?
<Style TargetType="{x:Type foo:Widget}">
?
</Style>
You could define a grid with 3 columns, the outer two defined to fill the remaining space equally and the middle to 50%:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="0.5*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
...
</Grid>
Then add the controls with:
<Button Grid.Column="1" HorizontalAligment="Stretch" />

XAML - user re-ordering of child windows (basically jquery UI sortable for XAML)

I have a Grid in a WPF application, which contains of 3 groupboxes and has grid-splitters between them.
I want to allow the user reordering of those 3 groupboxes as he wishes, so any mapping of the groupboxes to {left,center,right} positions is allowed.
In web-development world, I would use jQuery UI sortable to solve this.
Is there anything to solve this task for a Grid in WPF? Or any other container, that would provide the same functionality?
You can make 3 columns in your grid, and reorder the items by changing Grid.Column attached property. Your initial XAML will look like this:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0"> <!-- contains 1st groupbox --> </Border>
<Border Grid.Column="1"> <!-- contains 2nd groupbox --> </Border>
<Border Grid.Column="2"> <!-- contains 3rd groupbox --> </Border>
</Grid>
If you need to move the parts by drag-and-drop, you'll need to implement it manually, at least I am not aware of any framework which allows this out of the box.

How to make text wrap in a WPF TreeViewItem?

This time, my question is as simple as it sounds... how do you get text to wrap in a WPF TreeViewItem?
I have a simple HierarchicalDataTemplate with just one TextBlock in it.
<TextBlock Text="{Binding Value}" TextWrapping="Wrap" />
The text does not wrap.
I tried binding the Width of the TextBlock to the ActualWidth of the TreeView, but although that makes the text wrap, the Width of the TreeViewItem does not fit in the TreeView because the TreeView has Padding. Binding to the ActualWidth of the TreeViewItem has (unsurprisingly) the same effect. Another downside to this is that even the items with little text stretch outside the TreeView bounds.
<TextBlock Text="{Binding Value}" TextWrapping="Wrap" Width="{Binding ActualWidth,
ElementName=TreeView}" />
Surely there must be a better way, like somehow informing the TreeViewItem of the TreeView's bounds... I can't believe it doesn't know automatically. But how can I do this?
UPDATE >>>
Thanks to H.B.'s answer, I managed to change the Grid.ColumnSpan to 2 on the Bd Border he mentioned in the ControlTemplate and it set the width so that the text now wraps nicely. The problem is that I am using this ControlTemplate for other TreeViewItems in other TreeViews where I don't want full width items.
The solution I came up with is simple. I have bound the TreeViewItem.Tag value to the Grid.ColumnSpan property in the ControlTemplate like so:
<Border Grid.ColumnSpan="{Binding Tag, RelativeSource={RelativeSource TemplatedParent}}"
Name="Bd" Grid.Column="1" ... />
This allows me to change the Grid.ColumnSpan and therefore the full width or ordinary width behaviour of the TreeViewItem by setting the TreeViewItem.Tag value to either 2 or 1 respectively.
If you look at the default template of TreeViewItems you will see a Grid like this:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="19"
Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- ... -->
As you can see the third column takes all available space while the others are on Auto, the header is placed in the second column inside a border:
<Border Name="Bd"
Grid.Column="1"
...
This means that the column will become as large as the header, there is no restriction on it. Thus the header just gets bigger than the TreeView itself.
If you add Grid.ColumnSpan="2" to this Border it will occupy the third column as well, which is restricted by how much space is left, hence the text will wrap; this will however extend the header across the whole width which might look a bit odd when selecting it.
Of course you will also need to disable horizontal scrolling:
<TreeView ScrollViewer.HorizontalScrollBarVisibility="Disabled" ...

wpf - size problems for grid used as tabitem

I am having some problems with a menu that is displayed as tabs (displayed vertically on the left side)
I have defined a headertemplate that defines a grid consisting of two columns where the first holds a textblock with the text retrieved via binding. The second column holds an image whose visibility is tied to a property - this image is used by validation and shown when data entered in another view has been validated.
The problem I have is getting the columns to share the same width. Example:
Text1| Image
MuchLongerText| Image
This looks a bit wonky and so am trying to get the Images to line up but can't seem to do this. The HeaderTemplate has a datatemplate specified as below
<Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Text="{Binding Name}" HorizontalAlignment="Left" VerticalAlignment="Center"/>
<Image Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center" Width="20" Height="20" x:Name="ValidationImage" Source="/Images/validationimage.bmp"/> </Grid>
I've tried putting it in a stackpanel and using sharedsize but no luck. Any help with this would be much appreciated!
Cheers
/Sakic21
Take a look at the Grid.IsSharedSizeScope and DefinitionBase.SharedSizeGroup properties.

Resources