What is the best approach for creating binding at runtime? - wpf

In my application I want to create binding during runtime, and each object has to have a separate binding.
For example: I have two copies of a UserControl and each copy has property Text and it has to be bound to different data source.
And as Dependency property is static it won't allow to have a DP per instance, only one per class.
So I wonder what is the best approach to achieve it?

For dynamically working with data binding, check out the BindingOperations static class.
As far as using DPs, I'm not sure what you're asking. The DP itself is static, but the value of a DP is associated per-instance. Otherwise, how could multiple TextBox instances have different Text values? The bindings are specific to each instance, as well.

Are the two different data sources different types? Or are they two different instances of the same type?
I ask because the solution you're requesting - creating a binding at runtime - may be unnecessarily complex. You wouldn't normally need to create the bindings at runtime to solve the problem you've described. From what you've said so far about the problem, it sounds like a much simpler solution should work.
It's extremely common to have multiple instances of a particular user control, and for each instance to be bound to a different source object. You can do this with normal data binding expressions in Xaml. The trick is to rely on the DataContext to determine which particular each user control uses as its source. For example:
<my:MyUserControl DataContext="{Binding Path=Source1}" />
<my:MyUserControl DataContext="{Binding Path=Source2}" />
That'll create two instances of a custom user control, MyUserControl, and any bindings in the first one will attach to whatever object was in Source1, while the second will use Source2. So if MyUserControl.xaml contains something like this:
<TextBlock Text="{Binding Path=Name}" />
then that will bind to the Name property of two different source objects in the two different user control instances.
This addresses your stated requirement that each user control "has to be bound to different data source."

Related

Split view into two separate views

I'm building a WPF application which very simplified looks something like this:
I have an ApplicationView which holds the menu and a ContentControl.
The ContentControl binds to the property CurrentViewModel which is set by the menu and rendered by its related View (Views and ViewModels are coupled by DataTemplates defined in the App.xaml).
I found this approach on Rachel Lim's blog
So in this example my View contains a list of duties as well as a "Details" window of the currently selected duty.
This setup works fine, but I think my ViewModels are getting too fat!
The non-simplified version of this ViewModel is up at around 500 lines of code, for handling:
Initializing filters
Logic for filtering list
Displaying duty details
Add/Update/Cancel/Delete logic
Now I'm very new to WPF but that seems like too much code, yea?
And it will be even bigger before I'm finished with it.
Anyways, I was thinking that I could split the ViewModel into two separate ViewModels; one for holding list and filters and one for showing the details. But how is this best accomplished?
I have thought of two approaches, but don't know which is preferable:
Create a DutyMasterView whose sole purpose is to hold two ContentControls for the actual Views (ie DutyListView and DutyDetailView each with their own ViewModel)?
I'm using MVVM Light as my framework so I suppose I could use the messaging service to tell the DutyDetailViewModel which Duty to display, right?
Alternately create a DutyMasterViewModel which exposes the selected duty.
Ditch the DutyMasterView and nest the DutyDetailView in the DutyListView.
Does it make sense to split my ViewModel into two or should I just stick with my fat ViewModel?
If splitting the ViewModel is recommended which of my suggestions makes most sense?
Are there other approaches that I should consider?
If you're still looking for opinion, I'd do it almost like you mentioned in point 1 but you don't need any messaging.
You create two VMs. Let's say DutiesVM and DutyDetailVM. DutyDetailsVM contains just some string properties for ID and Name.
In DutiesVM you create two properties:
ObservableCollection<DutyDetailVM> DutiesList
DutyDetailVM SelectedDuty
Your DutiesView can look like this:
<DockPanel>
<v:DutyDetailV DockPanel.Dock="Right" DataContext="{Binding SelectedDuty}">
<ListBox ItemsSource="{Binding DutiesList}" SelectedItem="{Binding SelectedDuty}"/>
</DockPanel>
Now you can create ListView ItemTemplate that binds to DutyDetailVM Properties.
is usercontrol that defines the DutyDetail view. Selecting the item in the list updates the details control automatically.
That's just the sketch but I think you can get the point from it.

Using WPF without databinding?

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.

viewmodel have to be public. How should I deal with that?

Pretty much it summarizes my problem here:
Double check - does it ever make sense to have internal viewmodel class?
I have controls.DLL and I'd like to keep this custom control bindings and viewmodel's internal. However, this doesn't seem to be possible.
How do you get around that? The only way I see it - don't use bindings..
Why do you have a view model for a custom control? I assume you're assigning the view model object to the DataContext property, but this is almost always a mistake: the DataContext should be available to consumers to use and abuse as they please. Stated another way, what happens if a consumer of your custom control explicitly sets the DataContext? It sounds like your control will stop working and throw a bunch of xaml binding errors.
A custom control is inherently lookless. There is no model or view model, just a view. That view is the .cs file. You supply a default look via your themes/generic.xaml file, but consumers should be able to supply their own template. If you're tying them to a view model, they also need to know how to create a view model instance and all of its dependencies. You've just created highly coupled code. DI containers can loosen the coupling, but that just downgrades the relationship between classes from "coupled" to "related". I say, why do consumers even need to know that information?
A better approach is to provide all of the properties for your control as dependency properties. Then your generic.xaml can provide a control template that uses the more efficient TemplateBinding to bind properties/objects to your control. If you need to populate these dependency properties from a business object, expose another dependency property of type IBusinessObject and set the derived values in that object's PropertyMetaData changed handler. If your IBusinessObject type contains a property which is yet another class which implements INotifyPropertyChanged, you should probably (1) rethink your object graph or (2) create a Bnding object in code using the subclass.
I think following all of the above advice will eliminate the problem about which you're concerned plus the other problems as well. Leave the view models to the UserControls. And yes, this is why custom controls are a MASSIVE headache. Doing them right is fairly involved.
Try protected internal. I suppose this should work. Although I don't think its good idea to have the ViewModel not public at all, cause one of the purposes of it is to be able to define several Views against the same ViewModel, which may come from different assemblies.

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.

How to expose xaml properties?

I created a ComboBox subclass and added my functionality.
Now I want to expose external properties of the TextBox for example:
<a:MyComboBox SpellCheck.IsEnabled="True" TextBox.SelectedText="{Binding X}" />
Is this possible, I maybe didn't choose the wrong particular property but I guess you understand what I mean.
Is this possible?
Do I have to create all the properties individually?
This is not possible in XAML. XAML does not allow you to address sub-properties of individual members using a property path syntax like the one you describe. (Something similar is possible for certain inheritable properties such as backgrounds and font sizes, but that uses an inheritance mechanism -- affecting all contained controls -- rather than addressing a specific sub-element, and wouldn't work for TextBox.SelectedText anyway.)
So yes, you will need to declare custom properties on the MyComboBox class to surface the features of the TextBox that you need to access from outside the MyComboBox. On the plus side, this is good discipline for encapsulation: remember that a future developer might apply a custom template to your MyComboBox that doesn't include a TextBox (or the member isn't named TextBox, or the member named TextBox is actually a RichTextEditor instead of a plain TextBox...). Explicit properties ensure that MyComboBox defines clearly what behaviour and state such a template needs to respect, and lets the template decide how to implement that, rather than the author of the template being constrained always to expose a TextBox.

Resources