Is there a way to follow a binding in code? - wpf

If i have a Binding which has a property path and the data source can i execute it in code, to find the value?
The path that i am trying to follow can be quite complicated, including collection lookup and multiple levels.
there is a hack :
create a content control
use BindingOperations.SetBinding()
then retrieve the content
is there a better way?

You can avoid using a ContentControl, and write your own very simple class that derives directly from DependencyObject, and provides a single DependencyProperty, which you can then target with the binding. Aside from that, no, there isn't any better way - binding machinery in WPF is very much tied into the concept of dependency properties, and a binding cannot really be a "free-standing expression" that is just evaluated.

Related

How to use MediaElement.NaturalDuration to set MediaTimeline.Duration in WPF MVVM

My MVVM program is a media player and uses the Media Element's Natural Duration property to set the Media Timeline's duration. Before I implemented MVVM design pattern, I could simply put
MyMediaTimeline.Duration = MyMediaElement.NaturalDuration;
in the code-behind. I am new to using MVVM but I believe this is not the correct way to perform this action according to the MVVM design pattern. I believe that MediaElement.NaturalDuration is not a dependency property so it cannot be bound to directly. Do I need to make it a dependency property somehow? Would this be coded in the ViewModel?
When we need to implement functionality like this that relates to UI controls using MVVM, we have a few options. One is to implement some kind of service or manager class that can implement this functionality for us and another is to use Attached Properties. Out of these two options, I believe this second option to be more suitable for this problem.
However, there is absolutely nothing wrong with adding event handlers into the code behind of your view, even when using MVVM. I keep seeing new users panicking over what to do rather than use the code behind when using MVVM. This is a common misconception about MVVM.
If you really know how to use Attached Properties properly, then I would advise that you use one (or more) of those to solve your problem, otherwise I would happily advise you to use the code behind. Note that if your view models are correctly data bound to your views, then you can access your view model from the code behind like this:
TypeOfViewModel viewModel = (TypeOfViewModel)DataContext;

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.

Where should I set the DataContext - code behind or xaml?

(honestly I searched and read all the 'related questions' that seemed relevant - i do hope i didn't "miss" this question from elsewhere but here goes...)
There are two different ways (at least) to set the DataContext. One can use XAML or one can use the code behind.
What is the 'best practice' and why?
I tend to favor setting it in XAML because it allows a designer to define collections on their own but I need 'ammunition' on why it's a best practice or why I'm crazy and the code behind is the bomb...
A third way you might look at is using a locator service. I usually have one class that is responsible for the creation of all my DataContext(VM's in most cases for me) and I create an instance of that class in the App.xaml Resources. Then I bind the DataContext in the XAML of each individual page.
i.e.
<Page DataContext="{Binding ViewModel,Source={StaticResource Locator}}" >
I think it depends on what you are setting the DataContext to, and ultimately personal preference.
I personally always do it in the code behind of my views because I find it overall cleaner, and it was how I was taught MVVM. Another thing to keep in mind is, there are times you may need to change your datacontext depending on what you are working with. If this is the case it's much cleaner/easier to do in the code behind rather than in XAML.
As you can see by the answers so far opinion is divided. In truth there is no best practice (I do get bee in my bonet about discusions of "best practice" in the Silverlight world, its way too young for best practice to be truely known.)
The reality actually is that you can't set the "data context" in Xaml. Unless you actually construct an object instance like this:-
<UserControl>
<UserControl.DataContext>
<local:MyDataProviderThing />
Ultimately something external has to assign either the DataContext property directly or indirectly via another property or via binding (as in Stephan's answer). Its this external context which is dictates whether it makes sense to do it in Xaml or not. Many MVVM solutions use a binding in Xaml, in some cases simply to avoid there having to be any code at all in code-behind rather than it truely being "better". Others set up the DataContext in code using a base class that your control derives from.
DataContext of the user control/view I assume? One advantage of setting data context in the code behind is the availability of dependency injection. Your DI container can take care of any dependencies for you dynamically at run-time.
With this pattern, I frequently set a view's Blend design DataContext in xaml using d:DataContext. The "design version" can provide mock data for use in Blend, while the true implementation is resolved at run-time.

Is there any convinient way that i can deepclone 'style' instance in silverlight?

if a style is used, it can not be modified agaign. so i need a clone method. but its hard to implement.
what i want to do is implementing a cascading 'style' mechanism. for example, i set two style to the same frameworkelement. the same property of latter style will override the former one, while the different property remain unchanged.
but if i set the style property of the frameworkelement twice directly, the 1st style will be gone. so i use the baseon property of style class to do that. but now come across another problem, the style can not be modified after it's been set to a frameworkelement.
so now i need a clone method.
Kevin,
I have written a CloneObject class which is exactly what you are looking for. Check out my code here:
"Generic class for deep clone of Silverlight and C# objects".
Jim
thanks jim. i finally discards this 'clone' idea, because it's not that easy and seems to produce some buggy problem. so i try to create a xaml resource file, and every time i need to create a instance, i just load the xaml and call the XamlReader.load.
this can bring some performance issue, but i think the cost is acceptable. and i can do styling job in blend for that specified xaml file.

Parameterize ValidationRule in WPF

I've only scraped the surface of validation in WPF and have come across a scenario that is likely fairly common: I have a TextBox whose value needs to be validated against a variable data type, depending on the context. For example, if the context's data type is 'int,' then the TextBox needs to accept only input that can be converted to an Int32.
My first thought was to inherit from the ValidationRule class and to include the context and to use a switch inside the overridden Validate function, but I am unable to bind anything to it since it is not a FrameworkElement.
Any thoughts?
You can expose IDataErrorInfo. This lets you do data validation with complex logic.
Personally I don't like using IDataErrorInfo for something this simple because it requires a gratuitous creation of a ViewModels and a lot of extra code where none should be necessary. It should be as simple as this:
I have a markup extension that allows me to create a binding with custom validation code specfied as a C# expression. This is extremely simple to do, except for the C# parser: Just implement ProvideValue() by constructing a MultiBinding that uses a converter and builds the appropriate validation structure. This allows the validation expression to receive the containing DataContext and the user-specified Binding object in addition to the value being validated.
With this solution coded, you can do something like this:
BoundProperty="{my:ValidatedBinding
Path=SomeProperty,
ValidationExpression = context is TextBox ? (int)value>3 : (int)value<7,
Mode=TwoWay,
Converter=...
You could easily adapt my solution without the C# parser by creating the expression as a lambda in the code-behind and referencing it with x:Static:
public static reaonly Expression myValidatorExpression =
(object value, object context, BindingBase binding) =>
context is TextBox ? (int)value>3 : (int)value<7;
...
ValidationExpression={x:Static local:MyClass.myValidatorExpression}
In general I find this technique easier and clearer than using ViewModels. I still use ViewModels when there is a complex transformation needed, otherwise just pure XAML straight to the business objects layer.
Note that this approach assumes your business objects layer is not tied to any particular the back-end storage layout (eg SQL table structure). If it were, changing the back-end storage would require changing my UI and this would not be desirable either, so a ViewModel would be desirable from that standpoint. But if not, I always prefer to keep it simple and just use straight XAML.

Resources