So, I have an UserControl which is basically a Grid with 3 different DataGrids and some Labels. Seeing how I need to use this 3 times, instead of copying and pasting the code, I thought I'd just generate it once and use it in my main window.
I have defined the UserControl as:
<UserControl x:Class="Propuestas.UI.Andrei.DGMTX"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Propuestas.UI.Andrei"
mc:Ignorable="d"
Height="300"
Width="791.496">
And I am using it in my window as such:
<StackPanel Grid.Row="2">
<local:DGMTX/>
<local:DGMTX/>
<local:DGMTX/>
</StackPanel>
For some reason, it doesn't show up in the designer panel on my main window. Is there something I'm doing wrong?
Also, I would like to be able to bind based on a bound element. For example, let's say I have a class Model which has all the data that I need to represent in my UserControl.
I would like to do something like
<local:DGMTX Binding = {Binding Model}/>
and then be able to bind all of the other elements in my UserControl in its code. Is there a way I could do this in XAML? Or do I have to do it programmatically?
There are two ways to communicate your view model to controls:
As one commenter suggested, bind your view model to the data context of the user control. This enables binding everything in your view model to the inner workings of the control. Problem is the inner workings now depend on the data the object is associated with.
Create dependency properties for only the ones in your view model that the user control actually needs. I personally prefer this over the first in almost 99% of all cases because you know exactly what data the control expects and you can manipulate bound data in ways unique to the control that maybe the view model isn't responsible for.
Couple things to note about designer support when creating your own controls:
Visual Studio's designer still has a lot of issues when it comes to WPF. Don't believe me? Try referencing a dynamic resource defined in your main assembly in another. The designer will crash and tell you it can't be found. This isn't the actual case, however. As soon as you run the app, you will never see this exception.
In order to see changes made to source reflect in designer, you have to build the project first (the project in which the control resides, not necessarily the one it's referenced in). Sometimes, "cleaning" or (with better luck in some cases) "rebuilding" the project is the only thing that updates the designer in the main project when "building" doesn't work.
If after considering the latter and you still can't see anything, consider the implementation of the control. Is anything out of place? Did something accidentally get hidden? You may not think so at first and maybe it takes ten hours of frustration to succumb and check, but the little things can make all the difference.
Related
<Grid Name="mainSceneGrid" Grid.Row="1" Background="#FF075035">
<Grid Name="navigationGrid">
......
</Grid>
</Grid>
Normally from the code behind we would directly call navigationGrid.xxx which is very simple and effective. However when we start to get alot of dependent and nested grids for example it would be awesome to instead be able to call a property like this:
mainSceneGrid.navigationGrid.xxx
So we get some form of structured code and easier intellisense to work with, is this possible with xaml?
You misunderstand what the names of UI elements are.
For XAML, firstly, it is registering a name in the visual tree of elements using the FrameworkElement.RegisterName (String, Object) method and then searching in this tree using the FrameworkElement.FindName (String) method.
This is mainly used for bindings of type ElementName.
These names must be unique within the scope of the names.
Secondly, the x: Name Directive creates, in addition to the name in the visual tree, a field in the "* .g.i.cs" file.
This file is the XAML reflection generated by Studio Designer.
You can view it if you place the cursor on the call to the InitializeComponent () method and press F12.
It automatically changes when you change the XAML code.
And when you reference the name of an element in Code Behind, you are not actually referring to the name in XAML, but to a field in that file.
And if you know even a little about Sharpe, then you understand that you cannot create fields with names like name1.name2.
As for your problem, its origins are that you are not working with WPF in a way that is typical for WPF.
WPF is designed around the concept of UI elements getting values for their properties on their own through bindings.
Therefore, using WPF element names other than ElementName bindings is a sign of incorrect implementation.
Such incorrect implementation methods are fraught with the occurrence of specific tasks, code bloat, and a high probability of bugs and errors.
I advise you, especially at the initial stage of training, in general, do not even open the "* .xaml.cs" files.
There should be nothing in the Code Behind other than calling the InitializeComponent () method.
When you learn the basics of WPF (layout, bindings, data context, styles, templates, triggers, converters), then you will be able to consciously decide on the use of Code Behind.
But in practice, there are almost no such tasks where it is really needed.
I'm pretty new to WPF/XAML in C#, I saw some simple tutorials and stuff but, today I'm confused, never used to make UI there.
I need to output multiple forms which instance would look something like that:
(NB: I constructed it just in WYSIWG way, so XAML markup is total mess, it for screenshot. I cant even add table directly in grid, oh)
I got data like this for each month in schoolyear, so, depends on what class is choosen I want it to output like that (scheme)
(NB: instead of each CustomWindowInstance there I need my form from 1 st screenshot)
So, whats is best and simplies approach for that?
EDIT 1: I'll name XAML from the first screenshot, which represents controls you want to display multiple times, XAML 1, and another one, where you want to do it, XAML 2.
--
Almost ORIGINAL:
Create a separate User Control and move the content of Window tag from XAML 1 into it. Then you'll be able to show it as many times as you want by placing <yourUserControlNamespace:YourUserControlClass /> in XAML 2.
For an ability of communication with this control in XAML like <yourUserControlNamespace:YourUserControlClass Parameter="SomethingHere" /> you should implement a dependency property with name ParameterProperty (desired name of property in XAML + "Property") in YourUserControlClass.xaml.cs.
--
EDIT 2: One may also create a DataTemplate with parameter DataType={x:Type yourVMNamespace:YourVMClass} for the XAML 1's ViewModel (not View) in XAML 2's or the whole application's Resources. In that case the ViewModel class you are binding to will be represented by the DataTemplate's content itself. Later you can write <yourVMNamespace:YourVMClass /> as in the first solution.
This approach allows displaying rich representation of any items themselves, for example, in controls derived from ItemsControl, such as ListBox, all you've got to do is to bind ListBox's ItemsSource property to a collection of YourVMClass instances (or specify them in XAML by hand).
More precisely, in this case I won't call YourVMClass a ViewModel.
I'm in the process of learning WPF and currently exploring data binding. I have a DataGrid control on my form, and in my C# code for the form I have a List<string> variable.
I want to be able to use the Properties UI for the DataGrid in the designer to bind the List<string> to the DataGrid. I cannot figure out what I need to do or where I need to look in the UI to do this.
This is what I am doing:
Click my DataGrid in the UI designer to make it the active control.
Move to the Properties window.
Scroll down to the ItemsSource property.
Click on the field and the UI with Source, Path, Converter and Options pops up.
And when I get to this point I no longer know what to do.
I do not want to accomplish this by writing/modifying XAML. I want to know how it works using the UI.
Having never used the designer before, I can't be totally sure (your use case isn't quite clear either).
That being said, in my designer you
Set the "Binding Type" to "Data Context"
Select the "Custom" text box (needed for me because it doesn't see my DataContext)
Type the name of your property in the "Path" field (you can only bind to Properties)
Hit OK.
Note that this is the same as writing in XAML:
<DataGrid ItemsSource="{Binding MyItemCollection}"/>
<!-- or --!>
<DataGrid ItemsSource="{Binding Path=MytItemsCollection}"/>
There's a reason no one uses the designer....
The other options are more "advanced" binding concepts that you don't normally use on ItemsSource properties.
Note that DataGrid is a poor choice for displaying strings. ListView or ListBox are much better choices, as they don't assume your information has multiple pieces (like DataGrid does).
I understand not liking XAML, as it really intimidated me at first, but I will quickly say that it is a powerful tool. I am not sure how to do it through the designer, but in C# let's say you name your DataGrid 'myDataGrid' and your List is named 'stringList'. It is as simple as the following:
myDataGrid.ItemsSource = stringList;
and the data grid is now bound to your string list.
Thanks for asking the question! The properties window is so underrated.
First you must set the DataContext.
It's in the common section of the properties window. Set the data context to whatever view model you need. If you don't have a VM and the List is in the code behind, set the data context to relative source self.
Next in the Path write the name of your List.
Also, you may want to use ObservableCollection instead of List so your objects are updated in the UI as they change.
I was recently working with a lot of bindings to my configuration settings in XAML. Storing column widths/control sizes/window positions and the like. So I was wondering if there was an easy way to create and bind to "settings/configuration" values to XAML?
Right now I just create a setting in the project, shove a bindable property into the XAML's DataContext and go from there. But my settings count is getting pretty crazy and managing them is getting painful (boring, repetitive, and annoying).
In an ideal world I'd like a system where I can do something like this:
<Window State={Binding {Settings Name="MyWindowState", DefaultValue="Normal"}}/>
If the "MyWindowState" setting doesn't exist, it would be created automatically and stored somewhere. And if the MyWindowState setting changes, all the bindings that use it would also be notified and updated accordingly. And the DefaultValue would be used if the setting retrieval failed.
Does something akin to this exist already, or can it be achieved with the standard WPF XAML?
I am planning on working on something that can do this, but if a proven solution already exists I would love to at least look at it/hear it out.
From what I understand Telerik's persistance framework can do something like this, except on a control to control basis (there is no global "settings" I can bind to), at least on first glance.
Yes, it's quite possible. If you have an application properties file, you can access it like this:
Height="{Binding MainWindowHeight, Mode=TwoWay, Source={x:Static p:Settings.Default}}"
where MainWindowHeight is a setting (in my case, an int). You'll also need to include this in the top of your XAML file, in the Window or UserControl tag:
xmlns:p="clr-namespace:APPLICATION_NAME.Properties"
where APPLICATION_NAME is the name of your application.
EDIT: The binding can be have any mode, I just use TwoWay so I don't have to have any actual code to update it. For the positioning of my windows, it works out nicely that way.
EDIT: Also, this can't dynamically create settings. I would use an XML file in your application, make a class to handle that, and then bind to a method of the class to get/dynamically create the values.
You can do this with an attached property:
<Window loc:WindowState.Name="MyWindowState" />
In the OnNameChanged event handler of your attached property you will have access to the Window instance that the WindowState.Name property was set on and access to the value ("MyWindowState" in this example) that was set. There you start listening (e.g. using PropertyChangedEventManager) to changes of all properties of your Window instance that are part of your window state that you want to persist.
May be you can use WPF's theming option. You can store settings of your controls (width, color...) in a theme file, which is nothing but an xml file. You may store this xml somewhere and load it at runtime. You can update this xml when the application exits with the changes. And load it when the application opens next.
Well, i must admit, still sometimes XAML seems a bit mysterious to me. The thing is, i always liked to debug through the C# code (setting lots of breakpoints in them) to get the idea of "what is happening" and "how is it happening". But with declarative XAML syntax that's not an option. I think you'll agree that to work with XAML, or to be precise, to work with/understand some existing XAML code you got to "already know" how things work with XAML declaration. There is just no way you can know/learn things investigating the execution of your application code. So i'm more than interested to take a look through XAML inside-out, as detailed as possible. I'm NOT talking about "learning" XAML, I know the basic stuff. May be i can provide some examples to clarify the sort of things i'm looking for -
Compared to C# code how an object gets instantiated when we use them in XMAL? Are they stored in managed heap? Same way as C# code-instantiated objects?
How the properties get set while using Mark-Up Extension syntax for Data/Command Binding?
When any property of an INotifyPropertyChanged type gets updated, how the Binding instatnce inside the XAML syntax updates the itself? How exactly it gets notified it at the first place, & by whom?
A viewmodel can be set as the DataContext of a view at runtime by defining Typed DataTemplate, like -
<DataTemplate DataType="{x:Type viewmodels:AccountsViewModel}">
<views:Accounts/>
</DataTemplate>
How does it happen actually? What are the rules for setting DataContext other than searching for the DataContext property upward the logical tree?
How the whole template things (DataTemplate, ControlTemplate & ItemsPanelTemplate) are treated/resolved at run time.
etc. etc. etc.
So if you are good/experienced/expert in XAML what would you suggest (links, articles, blogposts, books whatever) as reference that helps getting clear & deeper understanding about how XAML works "under-the-hood"? Thanks in advance.
Most can be explained by don't thinking of XAML as a real programming language, more like a declarative language. Everything you do in xaml, can be made in C# aswell, and in fact this is whats happening.
Compared to C# code how an object gets instantiated when we use them
in XMAL? Are they stored in managed heap? Same way as C#
code-instantiated objects?
Yes because they are just c# objects. Most resources are stored in a hibernated state, i rememberd the word inflated somewhere. Converter or other "direct" c# objects are created when they are needed. Important here is that these resources are usually shared, so they will get created only once.
How the properties get set while using Mark-Up Extension syntax for Data/Command Binding?
This again depends on where you use the markup extension. In a Style? In a Template? In a instanced user control like a window? Usually they are evaluated when you actually need them. It wouldn't make sense to evaluate them, when the inflated style is stored in the actual resource dictionary. They get evaluated when you actually use the style on an object.
When any property of an INotifyPropertyChanged type gets updated, how
the Binding instatnce inside the XAML syntax updates the itself? How
exactly it gets notified it at the first place, & by whom?
By the binding engine. WPF checks if your DataContext inherits the INotifyPropertyChanged interface, attaches to the event provided by the interface and listens to any changes. If such an event is raised, the binding engine will just call the getter again.
How does it happen actually? What are the rules for setting DataContext
other than searching for the DataContext property upward
the logical tree?
In short: None other. Datacontext is simply an inherited attached property. If you don't re set it on a child control, it will take the value the parent has until it reached the root. The only exception to this are ContentControls and ContentPresenter they will not inherit the DataContext but will change them depending on the content. So these controls always have by default the Content as their DataContext.
How the whole template things (DataTemplate, ControlTemplate & ItemsPanelTemplate) are treated/resolved at run time.
Simply spoken: Everytime WPF finds a non ui object, it tries to find a DataTemplate for the given type. In an ItemsControl for example: You can bind a list of MyClass; unless you provide an explicit DataTemplate or DataTemplateSelector it will search the resource tree upwards for an implicit style. Again remember that this already does not happen in XAML, but on the C# objects that was generated out of the xaml.
And is it by any means possible (at present or near future) to debug
through XAML code?
How do you think you can debug something that is not executed, but evaluated on compile time?
Please don't take this as 100% correct. Over the Years this is what i gathered of informations about XAML and the usage. If you have any corrections or find something that is clearly wrong. Please tell me, we are all here to learn and i always learn new things about the stuff i use :)