How to change element in xaml that are in visual tree - wpf

I'm new to WPF and tyring to uderstand the best way I can modify any given control attributes. What I was trying to achieve is to show tooltip for a cell. Yes a quick google and can see xaml of how to do it. But I want to understand how can one learn to figure out this out using some tool.
I came across Snoop that can show visual tree of a control very easily (CTRL+SHIFT Mouse over). What I'm trying to understand is if one knows of visual tree, how can one change it? For example, let's say I use WPF DataGrid and bind it to a source and display column using DataGridTextColumn.
<DataGridTextColumn Header="First Name" Binding="{Binding FirstName}">
Now let's say I want to show tooltip for each cell. So I fire up Snoop and CTRL+SHIFT mouse over the cell. Snoop shows me that its a DataGridCell that is using Border and withing it ContentPresenter which ends up using TextBlock to show the value. So that means that if I can somehow access that textblock, I can set its tooltip property using binding. Issue is that I don't know how I can access it in xaml.
In other words, knowing a visual tree, how can one access it in xaml for any given control. This will also be very handly for 3rd party controls.
Thanks

Your'e asking quite a bit here, and i'm not sure I completely understand your intention, so I hope I got this right. Your'e asking if you can access the complete visual representation of each control and change it using xaml. The answer to that is yes, but you shouldn't.
I'll get to what I mean in a bit, but first I'd like to clarify some concepts, since i'm not sure you're using them correctly.
XAML:
Xaml is the declarative markup representation of your views and nothing more. Xaml syntax directly corresponds to it's respective classes and their properties. Xaml maps tags to classes and attributes to properties. It's a small distinction, but it's important to think this way. Everything you can do in xaml you can also do in code (although it would often be much more work). Again: xaml refers to markup code only.
<ClassA PropertyA="Value">
<ClassA.PropertyB>
<ClassB />
</ClassA.PropertyB>
Default property value
</ClassA>
Logical tree:
The logical tree is the runtime representation of your xaml code. it consists (mostly) of the controls you set in your xaml files.
Visual tree:
The visual tree is the visual representation the logical tree. It contains much more since it contains the concrete visual representation of everything displayed in your view. Most of the logical tree can't be directly displayed. WPF uses Data and Control Templates together with Styles to determine exactly how each object is supposed to look. In case of data templates that can also mean simple data objects and not only WPF controls.
Now for your question: so can you access the concrete visual representation of each control?
Yes, but you'll have to use control templates to manipulate it's visuals. Also, control templates are usually applied to control types and not specific controls, so you'll have to deal with that as well.
And that's why you shouldn't access it. The xaml representation usually gives you all you need to modify your control, and even if you do use templates you shouldn't change every last piece of it. Templates are used to style a control, so only write enough to show it as you wish. There's no need specify everything.
However you can access the entire visual tree more easily using procedural code, if you use the VisualTreeHelper class (that's how snoop does it, by the way). Using it you can traverse the visual tree and access all it's classes and members. If you really want to access every single visual object you'll do it much more easily with the VisualTreeHelper.

Related

Howto edit TopLevelHeaderTemplates PART_Popup in Expression Blend

I am very new to Expression Blend but can't find any solution with google. I would like to style a Menu and it's items. But how can I see the actual look of the PART_Popup? The IsOpen Property is bound to something like {Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}. It seems I am only looking at something complete invisible :). There is also a SystemDropShadowChrome but I actually can't see this thing. The eyes next to all the items are active. And even if I change some background colors all that I see is just a black transparent rectangle.
Is this a toolkit control (dropdownmenu) or a telerik (radmenu) or something? If you've already broken out the template (eg; Right click->Edit Template->Edit Current/Copy) Then there's a couple things you want to try to find it since sometimes they can be oddly embedded.
Go to the root level of the control, try Right Click->Edit Additional Templates->...
If that' doesn't provide your part_ look in your broken out template resource you've created and inspect your object tree. You're looking for embedded controls appearing as objects. Right click the embedded control in your object tree and edit its template (Current or Copy)
You'll potentially sometimes have to drill down multiple layers within a template to expose the objects you wish you to edit. If you specify which control you're working with I'm sure we can tell you exactly how to get to where you need more efficiently. Cheers!
Try exploring the States tab. Most likely some of the parts are only visible in certain states.

Access Elements inside a DataTemplate... How to for more than 1 DataTemplate?

I've got 2 DataTemplates defined for a Listbox Control. 1 Template is for the UnSelected State and the other one is for the Selected State(showing more detail than the UnSelected State).
I followed the example here:
Link
about how to access the Elements inside the DataTemplates from Code behind.
I get it right, but it only finds and returns an element of the UnSelected DataTemplate. But when i search for an element in the Selected DataTemplate i get a NullReferenceException.
What could i be doing wrong?
Setting keyboard focus might be one reason you need to access the datatemplate elements. MVVM will not solve that issue and the FocusManager doesn't set keyboard focus.
What you are doing wrong?
I would say what you are doing wrong is trying to access elements inside the DataTemplate from code-behind. Naughty, naughty!
All joking aside, 99.9% of the time I see someone trying to access an element inside a DataTemplate from code, it is because their application is poorly designed, with no (or few) bindings and no view model at all. Many beginners tend to store their data directly in UI elements rather than using a view model. I think it is because their minds have been corrupted by experience VB, WinForms, and ASP.NET where it was the "normal" way to do it. There are a thousand reasons to use a view model and bind your data instead of storing them in UI elements. Look up "model view view model" online for more details.
Now to answer your question:
Any given ListBoxItem can only have one DataTemplate at a time. This is because its ContentPresenter has only one ContentTemplate property, and this property cannot have two different values.
Because of this, the visual tree under a ListBoxItem will always be generated from one a specific template, not a combination of several templates. If you change the ItemTemplate of the ListBox or otherwise update ListBoxItem.ContentTemplate, the visual tree produced by the old template will be thrown away and a new one built.
Let me say that again: If you change data templates, the visual tree produced by the old data template will be thrown away and a new visual tree built.
You can have a hundred data templates defined and usable on a given ListBoxItem, but only one at a time can have a visual tree instantiated for it. And these are the only elements that actually exist as part of the visual tree. All other templates exist only as templates - there are no actual elements created for them.
To put it another way: It is meaningless to ask about how to find elements in two different visual trees instantiated by two different templates on the same control, because a single control cannot have two different templates active at the same time.
Hope this clears things up for you.
Final advice: Do read up on MVVM, and stop trying to access elements inside DataTemplates ASAP. However if you think you might be in that 0.1% who actually do have valid reasons to access elements inside templates, write back with your actual reason for wanting to do so and maybe I can provide further guidance.

WPF - Which one is better? Style or User Control?

I wanted to know which one amongst Style and UserControl would be better to use in WPF?
For example:
I have created an image button in two different ways.
One uses Style and ContentTemplate property is set.
It uses one other class with dependency properties.
The other way is I have created a UserControl which has a button and its content property is set.
The file UserControl.xaml.cs also contains the dependency properties.
For Code details see the answers of this question:
Custom button template in WPF
Which one would be better to use? In which scenario should one go for Style or UserControl or any CustomControl?
Styles are limited to setting default properties on XAML elements. For example, when I set the BorderBrush , I can specify the brush but not the width of the border. For complete freedom of a control’s appearance, use templates. To do this, create a style and specify the Template property.
Styles and templates still only allow you to change the appearance of a control. To add behavior and other features, you’ll need to create a custom control.
For example,
To create a button like a play button use styles and templates, but to create a a play button which will change its appearance after pausing it use UserControl.
For this type of thing I would go with Style, even though I'm not really adept with graphical tools. I tend to produce a basic, boring style that I can get started with and then prettify it once the application functionality has been verified.
The nicest thing about WPF is being able to distance much of the graphical look, feel and behaviour away from the code.
This allows you to change the style of your application without revisiting the code and indeed means that you can change styles on the fly at runtime.
There is an awkward line to tread with regards to how much behaviour is placed within the XAML and how much is placed within the code. A rough guide would be to decide on what behaviour must always be present within the UI and place that in the code, everything else place within the XAML.
Think of the code as being an abstract class with defined interfaces and the XAML Styles as being classes based on that class and you'll get an idea of what I mean.
Conversely, I know that people who are far more adept at the GUI work prefer to put more functionality in the XAML and others who prefer the code side, because they find the GUI work slow or difficult.
When thought of that way you'll see that there's never really a right or wrong answer, just better solutions that suit your skills.

How to create databinding over two xaml files?

I am trying to come to a working understanding of how databinding works, but even after several tutorials I only have a basic understanding of how databinding works. Thus this question might seem fundamental to those more familiar with silverlight. Even if it is trivial, please point me to some tutorial that deals with this problem. All that I could find simply solved this via adding the data binding on a parent page.xaml (that i must not use in my case).
For the sake of this example let us assume, that we have 5 files:
starter.cs
button1.xaml + codeBehind
button2.xaml + codeBehind
The two buttons are generated in code in the starter(.cs) file, and then added to some MapLayer
button1 my_button1 = new button1();
button2 my_button1 = new button2();
someLayer.Children.Add(my_button1);
someLayer.Children.Add(my_button2);
My aim is to connect the two buttons, so that they always display the same "text" (i.e. my_button1.content==my_button2.content = true;). Thus when something changes my_button1.content this change should be propagated to the other button (two way binding).
At the moment my button1.xaml looks like this:
<Grid x:Name="LayoutRoot">
<Button x:Name="x_button1" Margin="0,0,0,0" Content="{Binding ElementName=x_button2, Path=Content}" ClickMode="Press" Click="button1_Click"/>
</Grid>
But everthing that i get out of that is a button with no content at all, it is just blank as the binding silently fails.
How could I create the databinding in the context I described? Preferably in code and not XAML ;)
Thanks in advance
The chunk of documentation you need to read is this: XAML Namescopes
Your button1 xaml has a binding looking for an element with the name "x_button2". However in a real application there can be many controls which in turn have nested controls. All of these controls have all manner of UI elements some of which may have names.
It would be impossible to get anything done if all names throughout the entire application had be unique. Yet that would need to be true if it were for your button1 to be able to hunt down the existence of another control somewhere in the visual tree outside of that which it actually knows (its own xaml).
Hence each loaded Xaml document exists in its own "namescope" and the search for other elements with other names is limited to that "namescope".
The are various solutions to this problem depending on what you real requirements are as opposed to the simplified problem in your question.
Typically you give each of your controls a DependencyProperty to which the inner button Content property binds. In "MapLayer" as call it, could then bind the propert on one of your button controls to the other.

Should I be using Expression Blend to design really dynamic UIs?

My company's product is, at its core, a framework for developing metadata-driven UIs. I don't know how to characterize it less succinctly than that, and hope I won't need to for purposes of this question, but we'll see.
I've been trying to come up to speed on WPF, and have been building UI prototypes here and there, and recently I decided to see if I could use Expression Blend to help with the design of these UIs. And I'm pretty mystified at this point.
It appears to me as though Expresssion Blend is designed with the expectation that you already know all of the objects that are going to be present in the UI at design time. But our program generates these object dynamically at runtime.
For instance, a data row might be presented in a horizontal StackPanel containing alternating TextBlocks (for captions) and TextBoxes (for data fields). The number of these objects depends on metadata about the number of columns in the data row. I can, pretty readily, write code that runs through a metadata record and populates a StackPanel dynamically, setting up the binding of all of the controls to properties in either the data or metadata. (A TextBox's Width might be bound to metadata, while its Text is bound to data.)
But I can't even begin to figure out how to do something like this in Expression Blend. I can manually create all these controls, so that I have a set of controls that I can apply styles to and work out the visual design of the app, but it's really a pain to do this.
I can write code that goes through my data model and emits XAML for all these controls, I suppose, and then copy and paste it. But I'm going to feel really stupid if it turns out there a way to do this sort of thing in Expression Blend and I've dropped back and punted because I'm too dim to figure out the right way to think of it.
Is this enough information for someone to try formulating an answer?
I think expression blend is a very good choice ESPECIALLY if you want to design dynamic, datadriven UIs. You can use Blend to desgin DataTemplates that define how a single dataobject is to be presented to the screen. For example, if you have an object of type Person you can define the controls like textboxes, border etc. that then are to be generated automatically for each Person in your list.
You can then fill your ItemsControls (DataGrid, ListView, TreeView ...) with those dynamic databojects and WPF knows how to render them. If a Persopn is removed form the list, the generated visual item will be removed too. This is just a simple example the whole notion of dynamic data is deeply baked into WPF and you can access these features using blend.
To be able to design the datatemplates in expression blend you need to provide sample designtime data.
Also to be effective with all this it is of high advantage if you stick with the MVVM design.

Resources