Problem with "{Binding RelativeSource={RelativeSource FindAncestor - wpf

I'm working on a Prism Composite application where I load different views into a region. I need to make sure that the view I'm loading is resized to the same height as the region. Each view is a usercontrol that has a Grid as the outer element. I'm using the following code
<Grid Height="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ItemsControl}}, Path=ActualHeight}">
To set the height of the grid. My problem is that this exact code works fine for one view and doesn't for another view. On the grid that doesn't work, the height is what I would expect as if the Height property is not being set.
Any suggestions on how to trouble shoot this.

Without knowing much, I'd say this issue really just boils down to a binding issue. Debugging bindings is tricky, but there is a really great article on the subject here:
http://www.beacosta.com/blog/?p=52
Use the "diagnostics:PresentationTraceSources.TraceLevel=High" approach that Bea describes and find out what element you are actually binding to by watching the output window. That ought to help figure out why it's failing.
Good luck.

Related

Can you insert items between ListBoxItems in a ListBox?

Simple question. We want a divider to appear between each item in a horizontally styled listbox. Think the arrows between entries in a crumbtrail. However, we don't want that divider to be part of the selection, so it really should go between each ListBoxItem. Is it possible to do that?
The only two ways I can think to do this is to insert 'separator' items into the data and template them differently, but that requires mucking with the items collection, which you may not be able to do in a data bound situation.
The only other way would be to style the actual ListBoxItem to have a separator outside of the highlighting border, then template the last one in the list separately.
Can anyone think of any other way to do this?
Interesting question!
As you said, one way would be to mock the ItemsSource collection.
Such as:
<ListBox.ItemsSource>
<MultiBinding Converter="{StaticResource mockConverter}">
<Binding Path="YourCustomList" />
</MultiBinding>
</ListBox.ItemsSource>
Note that I used multibinding with only one binding. I believe that is the correct way in order for the converter to be "re-run". This way, when you modify items in "YourCustomList", it will retrigger the converter.
Unlike this, which will trigger converter only once(when ItemsSource is first binded against)
<ListBox ItemsSource="{Binding YourCUstomList, Converter={StaticResource mockCOnverter}}" />
^ wont work if you add new items.(Converter is only re-run when YourCustomList property changes)
MockConverter will be easy, just make sure you generate list with seperators. You need new class for a seperator. This way you can easily use DataTemplates(DataType). Next you probably have to set up a new trigger in ItemContainerStyle in order to set IsEnabled=false when object=Seperator.
It will be relatively painless and I see no complications. It's a little ugly because seperators should not be a ListBoxItems.
Perhaps this could also work.
You can override ListBox ItemsPanelTemplate with your own. In your own template, you can do whatever you want. Perhaps add seperators. This way, you wont touch ItemsSource.
Check out StackPanel.cs for code.
I can't provide with you a code right now, but the idea is this; you inherit from StackPanel, and overwrite Measure() and Arrange(). With those functions, you can calculate how big your stackPanel should be, and provide the location(X,y) where the seperators should be drawn at.
Note that the seperators have to be Children of StackPanel and they need to have IsHitTestVisible=False(so they wont generate events).
Later solution takes time, but if you are learning WPF, then why not?
DataTemplate is fine, I don't think you would have problems mocking the items collection. Why yould you ?
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Seperator/>
<TextBlock Text="{Binding .}"/>
</StackPanel/>
</DataTemplate>
I won't recommend the last option you had. That's just not right to have it separated style just to achieve what you want.

Link Rectangle.Fill to TextBlock.Background

I'm currently migrating from WinForms over to WPF and I'm really struggling with the binding aspects. All i need to do is match the fill property of a rectangle to a textblock.background and keep them in sync. I know I can do this with 'classic' event handlers, but I have 24 textboxes and 24 rectangles, and I'd prefer a more WPF solution. I've toyed with the binding properties but I can't seem to get any type of results since I have no clue with type of binding I even need! Do i need an event, or use a convertor, or possibly a style trigger? Maybe just stick transparent tape on the screen and call it a day?
I know the following doesn't work but this is my level of understanding at this point.
<Rectangle Fill="{Binding Source="textBlock.Background"} />
I've read various articles on databinding but they are all much more advanced, and typically deal with data.
Can someone please shed some light on this helpless n00b!
<TextBlock x:Name="SomeTextBlock" Content="Hi"/>
<Rectangle Fill="{Binding ElementName=SomeTextBlock, Path=Background}"/>
That's the easy way if you are creating them in XAML.

SelectedItem of SelectedItem

first of all I would like to thank you for the many good posts that i read in this forum. Unluckily I could not find anything of help for my current problem (either here or anywhere else).
What I'm trying to do sounds quite simple, but I have no clue how to get it to work ... perhaps I'm still to new to wpf or I don't thing wpfy enough :)
I'm designing a front end for a part in an automated manufacturing:
I have a quantity of places where pallets can be put (but it can be empty as well).
Each pallet has up to 3 places where parts can be mounted
Everything is created dynamically of a database and is reacting to changes.
The position of the parts on the pallet comes from the database as well and should be visualized
What I would like to have is:
An overview over the pallet-places with a preview of the pallet
When I select a place I want to see a detail view of the place
When I click on a part on the pallet of the detailed pallet I want to see details to the part
The first two points are quite simple and work nicely:
I have got a DataTemplate for every component (part, pallet, pallet-place). Actually those are UserControls that are imported as Datatemplates
the overview is a ListBox with the places as DataContext
for the detail-place-view I use the UserControl and bound it to the SelectedItem of the Listbox
I tried to bind the Text of a Textblock to the ID of the selected Part ... and fail.
Probably I could use some global variables in the code behind - but that sound very ugly.
Can anybody help?
I have got a solution ... it is not nice but works.
I created an event in the pallet, that triggers, when the selected part-place changes
I handle the event in the pallet-place and create a new one
And finally I handle it in the overview and change the detailview accordingly
Most likely there are much nicer solutions, but it will suffice.
Perhaps try an ElementName binding?
<TextBlock Text="{Binding ElementName=Name_of_your_Listbox, Path=SelectedItem.ID" />
Can you post a bit more code of your TextBlock and your Binding?
Context is important, if i use a ContentControl and bind its content to the SelectedItem like this:
<ContentControl Content="{Binding SelectedItem, ElementName=mylistbox}">
I can bind to the ID of the selected item in the DataTemplate like this:
<ContentControl.ContentTemplate>
<DataTemplate>
<TextBlock Text="{Binding ID}" />
</DataTemplate>
</ContentControl.ContentTemplate>
That is because setting the Content of the ContentControl automatically sets the DataContext as well, and this binding is relative to the DataContext since no source (ElementName, RelativeSource, Source) has been specified.
I do not know how your UserControl handles the context, if the DataContext is not affected such bindings will not work. You would need to bind directly then:
<uc:MyDetailsView Data="{Binding SelectedItem, ElementName=mylistbox}">
<!-- ... -->
<TextBlock Text="{Binding SelectedItem.ID, ElementName=mylistbox}" />
This of course defeats the purpose of having the binding on the UserControl itself in the first place. But unless you post some relevant code it's quite hard to tell what is wrong.
Also check the Output window in VisualStudio, binding errors will show up there and might provide valuable information as to what went wrong.

WPF TreeView: WordWrap

I have this project that displays hierarchical data with huge amounts of text, and I'm transitioning from winforms to wpf, and with winforms treeview not wordwrapping out of the box I really wanna know how to do this in wpf. Is it possible to have Items in the TreeView use word wrapping, out of the box?
I've looped through a fair amount of threads and google results, but none got me any working method. ScrollViewer.HorizontalScrollBarVisibility="false" got me nowhere either.
If its not there, how would one approach the implementation? I'm quite new to wpf, so I'd appreciate a direction to push in.
Oh, and the framework is 3.5.
I think you'd have to bind the width of the root control of the treeview's node template to the actual width of the treeview itself. So something like the following:
<TreeView x:Name="tv">
<TreeView.ItemTemplate>
<DataTemplate TargetType={x:Type TreeViewItem}">
<TextBlock Text="{Binding PropertyToBind}" Width="{Binding ActualWidth, ElementName=tv}" TextWrapping="Wrap"/>
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>
You should also be able to set the width binding using a relative source, but I can't recall the syntax.
Usually these types of problems are solved by forcibly constraining the element inside of its parent element (even though it should technically already do that). Just an idea. Good luck.

WPF Creating a ControlTemplate that is DataBound

I have a control bound to an Object and all is well but I want to turn it into a control template bound to different objects of a similar type. I would like to do this exclusively in xaml, if possible. Any good tutorials that outline the steps?
<TextBlock Text="{Binding Source={StaticResource BorderControl}, Path=ControlName}"/>
EDIT: With a little more experience, it turns out what I need is the ability to Set the Binding source based on a property of the control. i.e.
<TextBlock Text="{Binding Source={StaticResource {TemplateBinding Tag}}, Path=ControlName}"/>
The control exists within a ControlTemplate but works correctly if I bind it directly to the data -- if that makes a difference. I don't know if this is possible or if it's the correct approach. Any thoughts welcome!
EDIT:
This doesn't work either.
<TextBlock Text="{Binding Source={TemplateBinding Tag}, Path=ControlName}"/>
I think you want ContentPresenter here (http://msdn.microsoft.com/en-us/library/system.windows.controls.contentpresenter.aspx) - think of it as one line of an ItemsControl, it's got a content and a reference to a template that will represent that content.

Resources