Expose properties of a nested user control - wpf

I have a custom usercontrol created by myself which belongs to mine baseControls elements. It's a special button which have some animations and other cool features. It will be used stand alone in some applications, and wrapped into containers in other applications. In the last case I will have an userControl "WRAPPER" that will contain my "BUTTON". I need to reveal some properties (dependency properties) of the BUTTON at the WRAPPER level (i.e. ButtonStatus, Text, etc). A sort of tunneling of properties. I googled a little bit and I found an interesting solution at this link: Exposing Bindings as Properties of a Control but I don't know if its be best solution or if it's the only one! It consist in a sort of duplication of the properties at WRAPPER level...
Any Hints about this issue !??!
Thanks in advance
Paolo

Here is another StackOverflow thread that shows a solution on how to expose the inner element dependency properties. Basically, you add the the dependency property to the WRAPPER and bind the BUTTON property to the wrapper property. If the value flow is always from WRAPPER to BUTTON, you can use TemplateBinding instead of Binding.

One solution is, as you suggest, adding properties to the wrapper that mirror (and are bound to) the underlying properties you want to expose.
The other solution is to look into using attached properties.

Related

Mvvm light wpf navigation

What I want to achieve. A navigation service for MVVM Light WPF where I can easily say NavigateTo(View URI or ViewModel and a string name of the framework element that should present the View or ViewModel).
I first tried the View First approach from here.
https://stackoverflow.com/a/28968560/5272185
Problems I found with it was that the Frame frameworkelement seems to run sandboxed, and even though I set the view's datacontext to bind to a viewmodel retrieved from my viewmodellocator I seem to get a different instance inside the Frame. Also styles seem not to be inherit down into the Frame and the MVVM Light Messenger's messages do not seem to bubble up from the View shown inside a Frame.
Also the code to find the Frame element failes if the Frame is located within a ViewBox. I have no clue why but if I just remove the ViewBox it finds it correctly.
I ignored the ViewBox issue (removed the ViewBox) and changed the NavigationService to store ViewModelBase types instead of URI, and I changed the code to find a FrameworkElement of type ContentControl instead of Frame, set the ContentControl's content instead of a Frame's source. This so I should not run into the sandbox problem. This worked, but I now have no good way of switching to a detail view (using the same ViewModel as datacontext for multiple views).
Questions
When using a ViewModel first NavigationService as explained above, is there an easy way to show a detail view (sharing a ViewModel) without code duplication?
In case of a View first navigationservice exactly like the code in the link. Is there a way to make the Frame inherit the correct datacontext and styles (not running sandboxed at all)?
Can someone explain why the VisualTreeHelper code in the provided link does not find a framework element if the element is inside a ViewBox?
I should also mention that I have tried the approach to make a CurrentVM property and CurrentDetailMode property on the ViewModel and bind a ContentControl's content to the CurrentVM property and used DataTemplates with DataTriggers (bind to CurrentDetailMode) to set the corresponding View(s) to the ViewModels. According to this post.
https://rachel53461.wordpress.com/2011/12/18/navigation-with-mvvm-2/
It works well and supports detail views. My goal with the navigationservice is that I want to add all views or viewmodels to the service in one place. Not having to create the CurrentVM and CurrentDetailMode properties on every ViewModel that should be able to show different content / views. And I would prefer an easier solution than manually setting up Datatemplates with special DataTriggers for supporting "Detail" views. Also the navigation service discussed has a history queue so one can go back.
I managed to solve / answer my own questions
Just create a dumb ViewModel class for the Detail view, provide it with the (Main)ViewModel instance and make that ViewModel instance a property so you can bind to it. Done! Easy after all, and with Dependency injection it can become a breath.
See this link page.DataContext not inherited from parent Frame?
I solved this one and tracked it in the following separate question. See answer here
WPF ViewBox blocks VisualTreeHelper search

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.

Should a ViewModel in MVVM reference the View?

In the MVVM (Model-View-ViewModel) pattern should the ViewModel reference the view. I would think that it should not. But how should the following scenario be handeled? I have a view that has a tab control as the main container, the viewmodel for this view implements a command to add a new tab to the tab control. The easy way would be to allow the viewmodel to reference the view and then in the command implementation to just programmatically add the new tab to the tabcontrol in the view. This just seems wrong. Should I somehow bind the tabcontrol to the viewmodel and then implement a data/control-template to add the new tabs. I hope this makes some kind of sense to somebody :)
In "pure" MVVM, the ViewModel shouldn't really reference the View. It's often convenient, however, to provide some form of interface in the View whereby the ViewModel can interact with it.
However, I've found that I almost never do that anymore. The alternative approach is to use some form of attached property or blend behavior within your View, and bind it to your ViewModel properties. This allows you to keep the View logic 100% within the View. In addition, by creating a behavior for this, you create a reusable type that can be used to handle this in every ViewModel->View interaction. I strongly prefer this approach over having any View logic within the ViewModel.
In order to demonstrate this technique, I wrote a sample for the Expression Code Gallery called WindowCloseBehavior. It demonstrates how you can use a Behavior within the View bound to properties in the ViewModel to handle controlling a Window's life-cycle, including preventing it from being closed, etc.
Reed and Dan covered the general approach but in reference to your specific case, TabControl is an ItemsControl and so can bind its ItemsSource to a data collection in your ViewModel representing the set of tabs to display. The UI for each type of tab can then be represented by a DataTemplate specific to the data type of an item (either using DataType or a DataTemplateSelector). You can then add or remove data items as needed from your VM and have the tabs update automatically without the VM knowing anything about the TabControl.
I find that it's often a helpful compromise to expose an interface on the View that handles View-specific functionality. This is a good way to handle things that are awkward to accomplish with pure binding, such as instructing the form to close, opening a file dialog (though this often gets put in its own service interface) or interacting with controls not designed well for data binding (such as the example you provided.)
Using an interface still keeps the View and ViewModel largely decoupled and enables you to mock the specific IView during testing.
One of us is missing something obvious. Your tab control is an ItemsControl. You should bind the ItemsSource of your tab control to an ovservable collection in your view model. When you handle the command in your view model to add a tab, you simply add a new element to this collection and, voila, you've added a new tab to the control.

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.

WPF Dependency Property question ... need advice on what to do in this particular scenario:

I am attempting to create a sukodu (like crossword) player in WPF, and I realize that I have a whole bunch of controls that will need to know the sudoku grid to function.
Because of this, I think the Sudoku Grid object would be a good candidate to create a dependency property. I am about to start the work, but I have some lingering questions:
Who should own the SudokuGrid dependency property? I am thinking the main window UI element should.
Should I set it as a shared dependency property, where all user controls that represent a part of a sudoku grid simply add themselves to the property via .AddOwner() method?
OR
Set it up as an attached property, defined at the main window, and allow child user controls to set up accordingly?
I don't really want child controls to be allowed to set their own grid property value though, so at this time I am leaning towards shared dependency property, but I am not sure it does what I think it does.
Ultimately what I want is one property where if it's set on a parent UI element, all children UI elements that knows about the property will share the same value, overriding any prior value / setting. Does shared dependency do that?
I know it's a bit long winded, but any help would be much appreciated!
I think what you want is an attached property with the Inherits FrameworkPropertyOption. That we every control that wants to know about the grid can just find the grid by getting the value of the attached property (assuming it is set higher up in the tree). This article goes over attached properties and how to set them up.
Alternativly you might like to try out the Model View View-Model (MVVM) pattern and implement the Sudoku grid as a view-model class which each cell being a ceperate view-model class. That way the whole sudoku puzzel is completly seperate from the UI and the UI can just bind to it using appropriate data templates.
For more info on the MVVM pattern se the following:
http://www.codeproject.com/KB/WPF/MVCtoUnitTestinWPF.aspx
http://blogs.msdn.com/johngossman/archive/2005/10/08/478683.aspx

Resources