In an application of mine (this has to do with very dynamic navigation and content presentation) I have to use this construct in XAML:
<ContentControl Content={Binding ContentElement} />
So far, so good. This is great, absolutely great. I can host arbitrary stuff all over the place.
But there seems to be a strange, well, lets call it "phenomenon" in WPF (I believe it is in the BindingMarkupExtension, but not sure yet):
When my ContentElement property looks like this:
public FrameworkElement ContentElement
{
get
{
return this.m_ContentElement;
}
}
then the getter gets called TWICE (!!!) for each databinding operation (this includes when the user changes the language on the fly or reloads the hosting control).
However (and this is what is REALLY mind boggling for me):
When I change my ContentElement property to:
public object ContentElement
{
get
{
return this.m_ContentElement;
}
}
then the getter gets called once. Seriously, I'm not lying here. It is absolutely reproducible in the simplest applications, you can try for example by returning a new "TextBlock" (thats what I usually do to test or learn about more advanced WPF concepts).
Any ideas why?
The reason why I ask is that I hate the following consequences of the solution:
I lose type safety at this point
This may be a bit hard to explain to new developers or overly sceptical wisecracks
I was able to reproduce it for .NET 4.0 but it is not reproducible for the same application when you set .NET 3.5 framework in the preferences of project. In the case of .NET 4.0 - there are 2 calls for the getter if its type is FrameworkElement. But internal stacks are different. So it's definitely because of some internals of WPF 4.0. And well.. its quite hard to figure out why and how it works in this way. If time permits someone could investigate WPF internals with Reflector but I believe it's snowball's chance in hell :)
I had the same Problem and found an answer from Microsoft in another forum:
http://connect.microsoft.com/VisualStudio/feedback/details/554237/problem-binding-image-property-called-twice-for-each-item
As Kreol said, it is interesting to see that this was done in the .NET 4.0.
I don't know what to think about it. It certainly is done on purpose, to improve the performances or something.
In our case, we have a property that return a view of our model, and this view will be displayed in differents screens, so we can't implement a single field with a
if (_localValue != null)
statement, and must create a new Control everytime the property is getted.
So this may not be so performant anymore.
Any other thoughts?
Related
The WPF designer has a tough job to do. In order to show you a life view of your screen or component it has to execute code but, since you do not control the designer, it has to do this without producing any side effects.
So how does it do that? What are the rules around execution?
What if the view's code-behind code does logging to a file or a service?
What if the code-behind calls MessageBox.Show?
What if the code-behind doesn't have an empty default constructor?
I've hit situations before where I had a default constructor that was checking GetIsInDesignMode and creating and assigning a DataContext if false, and still the designer wasn't rendering correctly. Is there some sort of stack-depth limit?
What are the limitations?
it has to do this without producing any side effects
No, the designer is not that smart. If IsDesignTimeCreatable is specified, it will execute all code in a public parameterless constructor and in properties accessed by bindings. Specifically, it will popup message boxes, write to files, etc -- or throw exceptions trying (just try it yourself).
If you don't have a public parameterless constructor, it can't create an instance, so no code will run.
Regarding your question about "stack depth limit", I know of no such limitation. If you have a specific case where it's not working, I suggest you ask a specific question about that case.
In most cases where the designer fails it is because of an exception or other non-data-related problems (such as missing design-time resources). You should definitely guard code you don't want called during design-time using DesignerProperties.GetIsInDesignMode (I usually add a property IsInDesignMode to the base view model).
This is not exactly answering your question, but to be honest 'how does it work' is not a very specific question.
However rather than dropping this check in to your code-behind, are you aware that you can add something like this to your Xaml?
d:DataContext="{Binding Source={d:DesignInstance Type=namespace:className, IsDesignTimeCreatable=True}}"
This means that you can make a design-time version of your class, e.g. CalculatorDesign :
ICalculator, reference that in the Xaml, and each time you change and compile the design-time class the view will update within VS without running any code or having complicated logic in code-behind.
In the last days I studied MVVM and I downloaded a couple of samples.
The following article is very good and it included the source code:
Better User and Developer Experiences – From Windows Forms to WPF with MVVM
http://reedcopsey.com/series/windows-forms-to-mvvm/
When I first opened the project in Visual Studio 2013 all the fields and lists were empty like expected. The program is a RSS reader and I loaded one feed with lots of feed items which filled in all the fields in the form. But now even when I stopped the program I can see all the data in the design.
This is obviously very good because it makes it a lot easier to see and possibly amend the design.
I think what I saw is covered under the name Blendability – but I am not sure about this.
Now my question: Where does this Blendability come from? I looked at the source code of the project and I don’t find where the data comes from in design mode.
Over the last days I installed a couple of extensions in Visual Studio and maybe I installed something which causes this behaviour. Or maybe this is some special function in this example (which is not mentioned anywhere in the article).
If possible please let me know where this Blendability comes from and how I can implement it in my own projects.
Design time has a nifty feature where if you were to set the DataContext to a class, then that class will actually be instantiated at design-time.
It's quite probable that the DataContext of this particular window is a class with a constructor that executes the RSS reading code.
Take this for example:
public class MyRssReaderViewModel
{
public MyRssReaderViewModel()
{
//Read RSS and populate properties
LoadRSS();
}
public void LoadRSS()
{
...
}
...
}
Now if you were to set the DataContext like this:
<Window.DataContext>
<ViewModels:MyRssReaderViewModel/>
</Window.DataContex>
The designer will instantiate the class at design-time, and by extension call the LoadRSS method. Any elements that reference properties in your view model will update to display the bound data.
One important thing to note is that the class will be instantiated every time you build the project.
I have been tasked to design a contact management program for my company. We have VS 2012 and since I have never used WPF before I thought I would use it to develop this application.
I am having huge problem getting started on the binding when utilizing the entity framework for the database which btw is database first.
I have followed the instructions within this link to the letter.
http://msdn.microsoft.com/en-us/data/jj574514.aspx
The objects show up in the data sources window just fine. But when I drag and drop to my window, nothing happens. No idea what I am doing wrong and cannot find anyone else with this problem.
Can anyone help me out here? I have looked everywhere. Any help is appreciated
Ok. I actually went thru that article, just to show good faith and let you know that I actually want to help you.
I came to the following conclusions:
That article show a very basic scenario of getting data from an Entity Framework context and showing it in a WPF DataGrid.
It doesn't have any kind of validation nor business rules.
It doesn't have any UI behavior such as conditionally enabling/disabling or showing/hiding any UI elements.
That kind of scenario is where the Designer is useful, when you don't actually need anything except getting / saving data from / to a DB.
Unfortunately (or fortunately for all of us developers who make a living of it), most applications will require some level of validation and business rules and some level of UI logic.
The designer is really useless when it comes to developing complex logic.
You can use the designer for such situations where you don't require complex logic, however I must warn you the following cons:
The Visual Studio WPF designer produces fixed-size, fixed-position UIs. these type of UIs don't work well when executed in computers with different screen resolutions and DPI settings. Just like winforms.
It also produces XAML that has many unnecessary things (such as x:Name="categoryIdColumn" and things like Margin="13,13,43,191" which are really bad from a maintainabilty / scalability point of view)
From what I've seen, the designer-generated XAML also contains a CollectionViewSource, this is both a good thing and a bad thing. It's a good thing because it enables Design-Time Data in the DataGrid, but it is also bad because it bloats your XAML with lots of unneeded things and introduces unnecessary <Window.Resources> that complicate things up.
Now, this is the very minimal XAML needed for that DataGrid, without Design-time data support:
<Window x:Class="MiscSamples.DesignTimeDataGrid"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DesignTimeDataGrid">
<DataGrid ItemsSource="{Binding}" AutoGenerateColumns="False">
<DataGridTextColumn Header="Category Id" Binding="{Binding CategoryId}"/>
<DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
</DataGrid>
</Window>
You see? It's actually faster to type that (much more so with the help of Intellisense) than what it takes for you to browse the property window and set these properties manually.
My suggestion is that you get familiar with XAML instead of insisting in the hard way to do things
Another very important aspect to keep in mind is that generally speaking, you don't put anything in code-behind in WPF because it's not needed, therefore that tutorial is actually going against the WPF Way of doing things, but that's Ok because it's actually an Entity Framework tutorial, not a WPF tutorial.
ease of development
You really need to reconsider what you call "ease of development". When it comes to UI development, I call "ease of development" to actually being able to do what I want with the UI without having to resort to shitty procedural code practices involving P/Invoke (whatever that means) and "owner draw" type of things for evertyhing.
WPF provides REAL ease of development as opposed to the fake ease of development exhibited by winforms
winforms lets you do everything with a designer (and this is just because the code the designer generates is actually so shitty that nobody would have ever used winforms if they didn't have the designer) but then when it comes to adding complex DataBinding or UI logic you're stuck with winforms' incapabilities forever.
WPF encourages manual XAML writing, not only because XAML is declarative (as opposed to the procedural winforms approach), but also because the levels of customizability and reusability are so high that a designer-centric approach does not make sense.
drag and drop is the easy way out
No it's not. It's actually the hard way. The easy way is to learn XAML and be able to do Things you can't even imagine to do with winforms.
If a designer-centric approach still makes sense to you, you may want to try Expression Blend
Automatically Create Data Grids from Your Models
Using a data source to drag and drop a template onto a WPF control is an excellent and fast way to get up and running!
Start by doing this: In your project create a folder named Models, then use either Entity Framework DB first or code by hand the models you want to show.
OR see discussion below on Object binding...
In that same folder create a dummy class that is a property for IEnumerable like this..
public IEnumerable<MyClassModel> MyCollection { get; set; }
From there go to the Main Visual Studio menu, to View/Other Windows/Data Source and click that link.
Click on Object and find the MyCollection property just created above.
Now open a user control or window in WPF but keep the datasources toolbox opened.
It should default to a DataGrid, but you can right click on the datasource and change it to detail, datagrid or select individual properties of the class it represents.
Simply drag that datasource onto the XAML's grid area. The right click on the new stuff you see and click reset to set the content to be the size of the entire window.
After having done this you will have code injected into the code behind of the view as follows in the window loaded event of that window, usercontrol etc.
// Do not load your data at design time.
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
{
//Load your data here and assign the result to the CollectionViewSource.
System.Windows.Data.CollectionViewSource myCollectionViewSource = (System.Windows.Data.CollectionViewSource)this.Resources["Resource Key for CollectionViewSource"];
myCollectionViewSource.Source = your data
// }
Go back to the XAML and look for the CollectionViewSource KEY property that was also inserted when you dragged the property to the XAML. It looks like this:
Use the Key name in the code behind, and then "Bind" the CVS to your data source which is an enumerable of type MyClassModel it can live in the View Model or in the code behind of the view as you choose.
If you only use the CollectionViewSource to as the datacontext of the grid you do not need to implement INPC for any underlying collections! The CVS updates the view automatically everytime the source is updated! Once you get good at this you can create working View prototypes of data in 2 minutes! Forget hand-coding XAML that just takes too long.
Object Binding
Create a static class with a static method that returns something like this:
When using the datasource wizard choose the "Object" selection.
Click Ok and you should see something like this:
You have just mapped all of the properties into the data source definition.
For anyone finding this issue in VS 2022: as per this is written, VS 2022 has this known bug unable to drag and drop data source to XAML form.
More info: https://developercommunity.visualstudio.com/t/drag-a-a-table-from-datasource-and-drop-in-a-windo/1660788
UPDATE:
It says that the fix has been released on 15th June. You can try updating your VS 2022 to the latest.
I'm currently evaluating QtQuick (Qt User Interface Creation Kit) which will be released as part of Qt 4.7. QML is the JavaScript-based declarative language behind QtQuick.
It seems to be a very powerful concept, but I'm wondering if anybody that's made extensive use of other, more mature declarative-UI languages like XAML in WPF or Silverlight can give any insight into the real-world benefits that can be gained from this style of programming. Various advantages are often cited:
Speed of development
Forces separation between presentation and logic
Better integration between coders and designers
UI changes don't require re-compilation
Also, are there any downsides? A few potential areas of concern spring to mind:
Execution speed
Memory usage
Added complexity
Are there any other considerations that should be taken into account?
(Updated)
The misconception with XAML is that it's not compiled. It is indeed compiled down to BAML a binary pre-tokenized XAML. Apparently there was a IL compiled version of XAML too called CAML. The OP pointed me to this good article explaining what XAML/BAML and CAML are.
Anyway, to the question why to use it:
XAML is simply a Serialization Format for C# objects that it is particularly well suited to describe hierarchical object structures, like found in WPF GUIs.
What WPF helps you do is write less boring C# code like this:
var grid = new Grid();
grid.Content.add(new TextBlock() {Text = "Hello"});
grid.Content.add(new TextBlock() {Text = "World"});
and just express it in a more readable way like this:
<Grid>
<TextBlock Text="Hello">
<TextBlock Text="World">
</Grid>
Since WPF object nesting (putting stuff inside other objects) can get very deep, WPF makes it much easier to read than the resulting C# code.
As for separation of concerns: XAML helps here too since it does only allow you to express objects and their relationships/properties, rather than logic. That forces you to separate logic from UI layout. The MVVM Pattern is very well suited for this task and allows for eay testability and interchangeable Views.
Added complexity in XAML can be also easily dismissed because the same code in C# gets easily more complex than the XAML markup.
I can't give you any insight into QTQuick though. Sorry
QtQuick is extensible via C++ plugins, actually what the Qt guys recomment is that you do the UI, Animations, Transitions etc in QtQuick/QML while all of your business logic is in C++/Qt. So this way you get the best of both worlds, you can debug your C++ code like you usually do, while at the same time making UIs becomes effortless and extremely easy.
Also another important think about QtQuick/XAML is that they are hardware accelerated, so for example you can get pretty good fps without any effort. So they are not slow at all for what they set out to accomplish.
It saves time, soo much time. I did a UI with code in 3 days, did the same in QML in 2 hours.
The point of declarative coding, i.e. WPF or QTQuick is to provide a separation between the developer and presumably the artist that is implementing the visual aspects of your application. With regards to WPF, I find that debugging gets to be a bit harder. As we speak, I am compiling the latest QT to look at QTQuick. (It takes a long time and I have time to look at stackoverflow :-) ) So, I don't have an opinion on that yet.
QML/XAML are:
Great for MVVM pattern
Hardware accelerated (QML with using OpenGL for Windows, MAC, Linux and Phone OSes... XAML with using DirectX for Windows and its phone version)
Closer to artists
You can create a GREAT and NICE UI using XAML/QML
Easier UI implementation
Nice animation is possible
In XAML, usually you can create a Silverlight version of your application just with a little changes
In XAML there is some great features such as Template, Trigger (DataTrigger, Trigger, EventTrigger), Binding (in any side and also both side together), Resource, Commands, DependencyProperty and Notifiable Properties.
But please note in XAML: (I am a XAML programmer, therefore i have not points for QML)
XAML debugging is not possible
For any change in XAML, all program must be recompile
Be more careful for performance. For example if you use much many RoutedCommands in XAML, your application will be unusable!
In XAML, some feature not works as expected. There is unfortunately some tricks. (It should be clear... should works as expected... isn't it? )
Be careful for some similar namespaces like BitmapEffect and Effect. There is different features and costs. (e.g. BitmapEffect has some effects with software render and Effect has some effect with hardware render)
In real world, artists could not use WPF as Flash (at least with good performance).
Some features works on special places. For example DataTrigger works just in Style tag not in Resource section.
There is some weaknesses in XAML. Some examples: there is not any sequential animation... you cannot do any calculation in XAML (you must write a converter in C# even for a liiiittle work! JavaSript is a great replacement in QML)... some attributes are duplicate. e.g. x:Name and Name... Controlling View from ViewModel is not clear. e.g. closing View from ViewModel (you need some CodeBehind)
Tooooooo much run-time errors. If you use some tags in bad place it will notice you for syntax error, but many of errors occurs just in the run-time. e.g. if i target Background property (instead of Background.Color) for ColorAnimation, it will compile successfully, but in running animation... BUMP... runtime error!!! in such case on Expression Blend, application will crash!!!
Does anyone know how the databinding system works in silverlight technically, I have seen alot of the tuts on databinding and that items must be bound to a Dependancy Object ( and dependants ) using dependancy properties but where are the properties actually managed? what classes should I look at in reflector to understand the internals? I want a deeper look can anyone explain it better?
The data binding is handled by the unmanaged stack so you can't exactly do it but you can look at the stack in wpf a little easier. Essentially, the DependencyObject stuff is so that execution of changes is a lot faster than reflection can do. Remember this stack is also responsible for animation changes. (30-60x second).