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.
Related
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.
I need to create an application that will take an .ini file which will contain
min
max
default
values for the elements, allows user to edit these values and save a new .ini file. Since .ini files can not contain different elements in the specified groups the GUI needs to be generated dynamically.
From what I have read about WPF it largely stands on data-binding and Notifying Property changes.
Since my view model needs to accommodate different numbers of variables I am not going to have the ability to bind to properties, i was planning to attach one event handler to all text boxes which will pick the corresponding validation rule when the TextBox loses focus or Enter is pressed. After that, it should update the model accordingly if it passes validation and update the View using the model for the corresponding value.
I was wondering whether this sounded like a valid idea, whether there is similar design pattern I should read about or should I just steer away from WPF altogether?
You can still use bindings - since WPF supports item templating, and since you are using an MVVM pattern you can just create a VM for each sub-item in the list (you don't even need to do this you can bind directly in the template of each list item to a DTO or business object)
I'm currently doing a similar thing now - I have a list of material tests for a client, they want to have a variable number and type of tests for each material, but also be able to tweak and change those tests per order for their customer
They actually have two test types, but to describe the simpler of the two cases (which doesn't require child VMs as such) I just created an ItemsControl that has an item template:
<ItemsControl ItemsSource="{SomeBinding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{PropertyDescription}" />
<TextBox Text="{PropertyValue}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
In this case the model just contains a list of property names/values and displays them in a stackpanel (you may need to set the ItemPanel using an ItemsPanelTemplate. Obviously you could have an extended ItemsControl that allows a DataTemplateSelector to display a different data template per type (in fact WPF already support per-type data templates).
I'm currently using Caliburn.Micro which actually does a lot of setting up child-templates for you - so if you create the bound items as a VM you can do something as simple as this:
<ItemsControl x:Name="SomeBinding" />
And CM takes care of the rest as long as the child items in the SomeBinding property are VMs themselves (though that's another story :P)
Wrap this library with a class that implements INotifyPropertyChanged so WPF can update itself once properties change. That way you can effectively databind to an INI file.
I have problems figuring out where to use what xaml keywords because its hard to figure out what hierarchy it wants. It seems there is some grand design on how and where to use attributes, properties or child nodes.
<Node Attribute="True">
<Node.Property />
</Node>
I found this beautiful page explaining all the ribbon menu properties, but have no idea how to use them in xaml. After half an hour of searching and trying everything I managed to get an Icon to show in the ribbon menu button.
What is the logic behind this all and how to figure out what to use where?
How to merge the ribbon menu with the application bar (the top bar on most windows applications)? So I get a nice Ribbon Application Menu, like in the example.
Is there a way to turn off xaml background compliation? I'd sacrifice Intellisense for this.
Because the xaml editor performance is abysmal, the are many suggestions for this, but none working so far.
Edit:
I know the xaml syntax, but there's no hint on what hierarchy to use. So if I find the object I want to use (because they are all available) it will only say I'm using the wrong object, it should ask for the kind of object it wants to be in.
Also in normal programming when you use a reference you can always use all classes in it. With xaml we must suddenly know what reference our class came from, also it won't find the reference for you, you either have to try all references to see if they have a certain class or find a code example.
Good questions. Its a little hard to get a feel for exactly what you're asking for in your #1 question, but I'll take a brief stab at that one. I do have an answer for your #2 question. I do not have an answer for your #3.
"1. What is the logic behind this all and how to figure out what to use where?"
Like Clemens mentioned, the XAML Overview does a pretty good job at explaining things.
I'm guessing that one of the main things that you're asking about is basically "when do you use attribute syntax vs property element syntax". From that doc:
For some properties of an object element, attribute syntax is not possible, because the object or information necessary to provide the property value cannot be adequately expressed within the quotation mark and string restrictions of attribute syntax. For these cases, a different syntax known as property element syntax can be used....
Now about this part of your question...
"Also in normal programming when you use a reference you can always use all classes in it. With xaml we must suddenly know what reference our class came from, also it won't find the reference for you, you either have to try all references to see if they have a certain class or find a code example."
If part of your question is more about how can you more-easily handle your XAML (or more appropriately xmlns) namespaces so that it is easier to get references ironed out in your XAML, there is a technique that you may find useful. It lets you consolidate namespaces so that you can use fewer XAML namespace prefixes (or even no namespace prefixes if you take this technique to its extreme).
"2. How to merge the ribbon menu with the application bar (the top bar on most windows applications)? So I get a nice Ribbon Application Menu, like in the example."
Essentially it seems that you're asking how to: (a) extend the window chrome area (the Aero glass area) down into the client part of the window (the part that your application normally gets to put things) and (b) extend the client part of the window up into the window chrome area. If you can do both of these things, then you can end up with something that looks like Microsoft office products or modern web browsers. Fortunately there is the WPF Shell Integration Library which helps you do both of these things. I found this blog and this blog (and the source code they offer) good guides for getting started with using the WPF Shell Integration Library.
Using this library, I was able to make this window (all but the Aero color changing abilities which is a whole other topic). Notice that both of qualities I mentioned are working here (the TabControl is being display up in the normal window chrome top bar area and the window chrome Aero glass is being displayed down in the normal client area):
Here's my take
1) What is the logic behind this all and how to figure out what to use
where?
Whatever you can fit between "" can go inline like:
<TextBlock Text="{Binding Name}" />
Whatever can't, go the element way:
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} ({1})">
<Binding Path="Name" />
<Binding Path="Gender" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
2) How to merge the ribbon menu with the application bar (the top bar on
most windows applications)? So I get a nice Ribbon Application Menu,
like in the example.
You'll find more or less complicated mumbo jumbo around google, this is the essence of it:
<Window ...
WindowStyle="None" AllowsTransparency="True" Background="Transparent"
...>
<!-- Fill it up with a PNG image if you want to play with transparency -->
</Window>
Then make the ribbon the top element, and re-create Close/Maximize buttons
3) Is there a way to turn off xaml background compliation? I'd sacrifice
Intellisense for this.
Yep, it's called Notepad++
Is there a way to pass parameters to a resource dictionary? I think that I can attach a code behind for the purpose of specifying event handlers, but unfortunately, I also need to access a reference to the parent control from the event handlers. The codebehind, I believe, can be attached by specifying an x:Class attribute for the resource dictionary in xaml, and then creating a class in the same folder, the filename for which is something like [resource dictionary name].xaml.cs.
The purpose is to seperate the code for four hierarchical data templates that I'm using in a single treeview control. The xaml for the treeview is getting a bit long and ugly to look at, so I was hoping to break it down into four resource dictionaries. Any thoughts are welcome!
Andrew
You know you can merge your Resource Dictionaries and then reference the DataTemplate within those dictionaries as needed within the TreeView.
Resource dictionaries sound like a slightly peculiar way to do this. Resource dictionaries are all about sharing instances - they let you use a single instance of something (e.g. a style, a template, a brush, or whatever) from multiple places. They're not really a mechanism for dividing your UI up to simplify individual Xaml files.
The usual mechanism for splitting overly complicated Xaml files up into a few, more manageable smaller files is the user control. (Resource dictionary merging comes into play when you already have a resource dictionary, and it's got too big. But you wouldn't normally introduce a resource dictionary just to start splitting things up. On the contrary, resource dictionaries tend to encourage overly large Xaml files, which is why dictionary merging had to be invented in the first place!)
Most of the time, when I define a data template, I make it contain nothing but a single user control. And if that becomes more complex, I'd split that user control up into more user controls.
From your description, it sounds like your Xaml file has become large because you've got four large hierarchical data templates in there. If you took the body of each template and turned it into a user control, your four templates would now become very simple - something like this:
<HierarchicalDataTemplate x:Key="t1" ItemsSource="{Binding Path=Children}">
<loc:TreeItemTypeOne />
</HierarchicalDataTemplate>
and you'd most likely no longer need to put those templates into separate files. But because the guts of each template is now in a user control, that gives you a place to put your codebehind.
You mention needing a reference to the parent control. That worries me - it makes it sound like you have too much code in your codebehind. But one thing at a time... You could solve that problem by defining a dependency property called ParentControl on your user control, and then put this in the template:
<loc:TreeItemTypeOne
ParentControl="{Binding RelativeSource=
{RelativeSource AncestorType=loc:ParentControlType}}" />
But frankly, as soon as I find myself in a position where I need this, I ask myself: how did I get myself into a position where that seemed necessary, and what can I do to fix that?
I have these ViewModels: RecordViewModel, ComponentViewModel where RecordViewModel essentially is a container for several ComponentViewModels.
The display of these ViewModels is currently handled by DataTemplates that look something like this:
<DataTemplate DataType="{x:Type vm:RecordViewModel}" >
<ItemsControl ItemsSource={Binding Components} />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:ComponentViewModel}" >
<TextBox Text={Binding Name} />
</DataTemplate>
What I wanted to provide now is a way to change the order the ComponentViewModels are displayed and to remove a certain ComponentViewModel from the list. I started out doing that by manipulating the DataTemplate of the ComponentViewModel and adding buttons that provided these functions (the click would then trigger a method on the ComponentViewModel that would (through a reference "Parent" to the RecordViewModel) call a method on the RecordViewModel to perform the operation (like component.Parent.DeleteComponent(this)).
The problem with this in my oppinion is that it is really the Record that should manipulate the Components position/remove a Component and not the Component itself.
So I thought about using an adorner that attaches to the RecordViewModel and renders the buttons to provide the functionality (remove, move up, move down) for each of the ComponentViewModels.
The problem however is that these adorners need to take a reference to a Control-derivate which they adorn (which was ok I would just bind to the ItemsControl in the Record-DataTemplate) however the problem appears when I want to show the buttons in the right position for each ComponentViewModel. I only have a reference to the given ComponentViewModels and not to their visual representation (the thing defined in the DataTemplate) so I have no way of knowing where to place the 3 buttons.
Is there a way to work around this? Or is it possible that for these requirements using ViewModels/DataTemplates is just not a good idea and should I therefore use Control-derivates/ControlTemplates?
Thanks in advance!
Coming up with wacky architectural hacks that you can employ to keep your view model elegant and simple is missing the point. The view model is the wacky architectural hack.
The only reason - seriously, the only reason - that the view model exists is to model the view. Does the view have buttons that trigger commands? The commands belong in the view model.
Thinking, "it's really the Record's responsibility to move Components" seems sensible on its face, but it's actually an indication that you're losing track of why you even created a view model in the first place. Does the Component view have a "Move Up" button? Then the Component view model needs a "Move Up" command that you can bind the button to. Because that's what the Component view model is for.
I'm being emphatic about this because this is the third or fourth question I've seen this week from WPF developers who seem to have gone down so deeply down the rabbit hole of the MVVM pattern that they've forgotten why it exists.
If your goal is to have a Command on the parent ViewModel that acts on an element of the child ViewModel, you can do this by using a RelativeSource binding on Command and passing the item as Command Parameter:
<DataTemplate DataType="{x:Type vm:ComponentViewModel}" >
<Button
Command="{Binding DataContext.RemoveCommand,
RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding}"
Content="{Binding Name}"/>
</DataTemplate>
The RelativeSource binding will find the ItemsControl, so the DataContext property will be your RecordViewModel. The CommandParameter will be the individual ComponentViewModel, so your ICommand implementation would be:
DeleteComponent((ComponentViewModel)parameter);
it is really the Record that should manipulate the Components position/remove a Component and not the Component itself
As far as your model objects go, that's probably true. However, the ViewModels are all about presentation, and the buttons are kind of part of a Component's presentation. So I think it could be acceptable for the ComponentViewModel to have a reference to its parent RecordViewModel, to enable this scenario, even if it wouldn't be appropriate for the Component to have a reference to its parent Record.
But consider that, in your scenario, maybe the ComponentViewModel has too many responsibilities. It belongs to the collection (because it's mutating the collection), and it belongs to the element in the collection (because it's showing the Component's name in a TextBox). It sounds like it's this dual responsibility that's bothering you. So break it up. Make RecordViewModel contain RecordElementViewModels, each of which knows how to remove itself from the Record; and each RecordElementViewModel contains a ComponentViewModel. On the view side, it sounds like your UI would be composed the same way: an outer panel with a Delete button, and then another control or panel inside that, presenting the Component's properties.
Now, for the example you posted, where Component's view is just a TextBox, I wouldn't bother splitting the ViewModel into two parts. But for a more complex example, it might make a lot of sense.
To specifically answer your question about adorning:
You're getting into changing the way a DataTemplate-d element is laid out, which means you're not just layering an adorner on top of the element, you're actually wanting to insert a panel into the visual tree that imposes its own layout onto the DataTemplate (which becomes a child of the new panel). I'll admit that I haven't used adorners, but that doesn't seem to be what they're for.
The best way to do this, IMO, is to have your DataTemplate generate the parent panel, buttons and all -- which leads back to wanting the functionality on the ComponentViewModel, or perhaps splitting ComponentViewModel's responsibilities (see my other answer).