How to dynamic add/remove control with Expression Blend? - wpf

A while I go, I made a demo application with Expression Blend.
My first screen is a big selections of Buttons, so when user click on any of button, it goes to the MainView.
Then in the MainView, I have a list of Menu items that user can click and shows up its corresponing DisplayView. (Appointment Menu Item will shows up AppointmentView etc).
Everything is good, I can click the MenuItem, the Views shows up with animation and transition effects.
But the thing is, with creating in Expression Blend, the MainView, Menu, AppointmentView etc every thing is predefined in the XAML. So when user load the first screen has to load everything into memory.
Now thinking of it, shouldn't the MainView etc be dynamically add into the screen?
How do I do it with Expression Blend? Or the only way to do is just....do it in code-behind myself (writting StoryBoard etc for the dynamic add/remove controls?)
If there is any example/tutorial of doing it, it will be great.

I guess you have very limited possibilities to conditionally load or unload controls exclusively in Blend without writing code-behind.
In general an opening tag in XAML is equivalent to a parameter-less constructor of some class object. As soon as you write the tags your are instantiating an object but that doesn't mean that it's visual appearance is loaded into memory. This only happens when the control is actually shown on the screen.
In my opinion the leanest way to control the appearance of some control is to use a single-child control. Take a Border control for example and add the user control you want to conditionally load to its child property, so you can decide for example whether to load or unload a control.
But unfortunately I think you have to do this in code as well. Take this easy code snippet:
// either instantiate in code or use from markuup
Border myBorder = new Border();
// the control you want to conditionally appear and disappear
UserControl myUserControl = new UserControl();
myBorder.Child.Add(myUserControl);
Of course a much more sophisticated approach is to use Grids. Here you have to use attached properties to add or remove child elements:
// either instantiate in code or use from markuup
Grid myGrid = new Grid();
// the control you want to conditionally appear and disappear
UserControl myUserControl = new UserControl();
// set the target position inside the Grid via the Grids attached properties
Grid.setRow(myUserControl, 1);
Grid.setColumn(myUserControl, 0);
// actually add the control
Grid.Children.Add(myUserControl);
Although I am pretty sure you were aware of all of that I am hoping it helped a bit :)

Related

Winforms Databinding and multiple Forms

i have a main window that contains multiple UserControls, arranged as tab pages and tab groups (much like Visual Studio allows to have two or more editors visible at the same time).
I also have the possibility to open such an UserControl into a seperate floating window.
One of these UserControls contains simple form fields (e.g. text boxes). These text boxes are bounded with common databinding to an object / property. The binding mode is OnValidation (not on OnPropertyChanged).
When I switch the focus from this User Control inside the main window into another UserControl in the Main windows, the validation is automatically performed and the databinding is finised / the changed text will be set on the model object / property that is bounded to that text field.
But if I switch the focus to an UserControl which resides in another (floating) window, the databinding is not finished since no validation is performed.
I know that I can handle this manually by triggering ValidateChildren etc, but this seems to my the wrong way / is ugly.
Is there a "correct" / clean way to solve this issue? I want that the validation is performed as soon as the UserControl loses its focus or the window gets deactivated.
One information: On of my UserControls contains a TreeControl. If I edit a tree node label, and when I switch the focus to another (foating) window, the label edit is finished automatically. I want the corresponding behaviour for usual form fields regarding binding...
Thanks for help!
There is no automatic way to do this. From the point of view of the control, it still has the focus (if you click the title bar or Alt-tab back to the main window, you will notice that the focus remains in the same control). Its just that the form the control is on is not active. If you want it to save changes when your form is deactivated, you must manually trigger it. The best way to do that is probably to override the OnDeactivate method of the form.
protected override void OnDeactivate(EventArgs e)
{
base.OnDeactivate(e);
this.ValidateChildren();
}

WPF contentcontrol extend beyond the bounds of its parent control

This is a sort of extension of this question I asked yesterday (the question gave me a contentcontrol that can overlay the current control). I now have a contentcontrol that can be overlayed on the current control via bindings (a modal type window). This works well and I am happy with this. One great feature would be if I could get the overlay to go over its parent.
currently the overlay will go into "My Control" control. What I would like is if I can still define it in that control (as that is were it is needed), but when it is displayed it can cover the whole main content area and / or the main window.
is this even possible?
Thanks
Sure it's possible, just wrap it into a Popup! :) You might have to manually stretch it though, but Popup is the control which will let you go outside the bounds of the parent view.
Another way is to host the MainContent in a grid and add a collapsed content control after the MainContent.
To show the popup: put it in the collapsed content control and make it visible.
To hide the popup: collapse the contentn control and remove the popup.

Re-using Buttons in WPF

I have a bunch of different objects that are commonly edited in the same TabControl using different DataTemplates, but I want each DataTemplate to have a common look and feel with Ok and Cancel buttons at the bottom right of each tab that will close the tab or save the content and then close the currently selected tab. What's the best way to place buttons on each tab ? Is there a way to do it without copying and pasting the buttons and stack panel across all of my data templates ?
Sure, you can create your own OkCancelSaveControl. In WPF, creating a "user control" is much easier than it sounds. Here is a tutorial. In a nutshell, you
create a new user control,
create properties in the user control that give the your control the information it needs to perform its duties (e.g. the tab that it's supposed to close or the data object that it's supposed to save),
if necessary, create events that the user control raises (OkClick), in case some tab requires special treatment.
I would make a custom control, lets call it MyCoolTabItem, that inherits from the TabItem class, and just throw your buttons into the control. Then just add a MyCoolTabItem instead of a TabItem to all of your TabControls and it will have all of your buttons on it.
You could make a base view class that held those buttons. Views that needed the buttons would inherit them and common functionality.

Error window show modal in MVVM WPF

I have implemented my MVVM error message as a message dialog that subscribes to error messages via a mediator class, so that other viewmodels can notify it if any errors occur.
When an error occurs, I set the visibility attribute in the viewmodel to Visible, to display the error window. This is all bound in the Error window from the viewmodel.
However, this window is NOT modal! I need to show it as a dialog and not just set the visibility to true - is there any kind of binding I can do, even if I have to extend the functionality of the window? I'd rather not break MVVM if I can avoid it.
Thanks!
The View/ViewModel split is meant to divide look from functionality. I firmly believe the Window is functionality and look rolled into one. For instance, what if in your ErrorMessageViewModel, you had this code that executes when there are errors:
class WindowViewModel : Window
{
}
.
.
.
WindowViewModel newDialog = new WindowViewModel();
newDialog.Content = myErrorListViewModel;
newDialog.Parent = mainWindowViewModel;
newDialog.ShowDialog();
So the contents of the dialog is the ViewModel for your error list. Define your View as a data template that automatically applies itself to the error list ViewModel.
Doesn't that look like MVVM?
The fact is, the Window class is a ViewModel for the Window you see on the screen. By changing the properties of the Window object, it affects the "view" just like if the properties of the WindowView were bound to a WindowViewModel. The only thing missing is the ability to "restyle" the Window using WPF, and it doesn't matter how hard you try to implement it, you're not going to be able to do that. The user can restyle a Window by modifying their desktop theme, but you're not in control of it. The best you can do is turn off the chrome and/or make it full screen.
You find an example how windows (don't matter if they are modal or not) are shown, in the ViewModel example of this project:
WPF Application Framework (WAF)
http://waf.codeplex.com
I am also working on a MVVM project where I need modal dialogboxes or messageboxes. I have found the following way of solving it:
The software uses only one window. The layout root element is a Grid with no row- or columndefinitions. The grid has three children:
A dockpanel that contains all the usual stuff like menus, tabbed views, status bar and so on.
A grid that has a gray background and a 50% opacity. This is used as a veil to cover the dockpanel when a modal box is in effect. The veil grid is usually collapsed.
A grid holding modal views, this is usually collapsed.
The viewmodel for the main window has a member called Modal. If this is null, the two grids for modal use are collapsed through databinding and a converter for Visibility.Collapsed.
When the program wants to display for example a modal message box, a MessageBoxViewModel is instantiated and assigned to MainViewModel.Modal. The MessageBoxViewModel has a Command for an OK-button. This Command raises an event that sets the MainViewModel.Modal to null again.
The veil grid occludes the main DockPanel, so that no controls outside the Modal control accept input.
Your program can either run a messagepump until OK is pressed, or the OK-Command can trigger the next. There are many ways of solving different needs, but the Model-ModelView solution should support them.
I feel that this is as good a model of the view in the modal mode as one can hope for.
I made a behhavior to tie some modal dialogs to the command.
http://www.clr-namespace.com/post/MVVMModal-dialog-before-running-Command.aspx
<Confirm:Confirm IsConfirm="{Binding ElementName=checkBoxConfirm, Path=IsChecked}"
Command="{Binding Path=ButtonCommand}"
CommandParameter="{Binding ElementName=textBoxParameter, Path=Text}"
ConfirmMessage="Are you sure you want to fire the command?"
ConfirmCaption="Question" >
</Confirm:Confirm>
In my recent blog post you can find simple solution for Modal Dialogs and Message Boxes in MVVM for Silverlight but this can be simply reused in WPF:
Modal dialogs with MVVM and Silverlight 4
i'm using the same method as Scott Whitlock.
there is just one more important property to set:
class ModalDialog: Window
{
}
.
.
.
var dlg = new ModalDialog {
Content = viewModelName,
**TopMost = true,**
Parent = mainWindowViewModel
};
dlg.ShowDialog();

Does Visual Inheritance work with User controls in VS2008

I have a base User Control. I place Ok and Cancel buttons on the bottom right of the control and anchor them Bottom and Right.
I then create another user control that inherits from the base user control. I resize the inherited control (e.g. increase height or width). Throw the inherited control onto the form. Run. The inherited control does not honor the anchor properties of the Ok and Cancel buttons.
Here are the exact steps to repro.
1 - Create a new winforms project
2 - Create a base control (BaseControl1) with a Ok and Cancel buttons located at bottom/right. Anchor them there at Bottom,Right. Compile the app.
3 - Create a new User Control (UserControl1) that inherits from the base control (BaseControl1), created in step 1.
4 - Increase (in the designer) UserControl1's height or width.
5 - Throw UserControl1 onto Form1. Run. You'll see that Ok and Cancel buttons are not where they are supposed to be.
Am I doing something wrong, or does VS2008 simply not honor the anchor properties of the controls on the base user control?
Change the Modifiers property on your buttons to Protected. Then, after you complete step 4, you'll notice the designer code for UserControl1 now contains a line of code to set the buttons' locations. That wasn't happening when your buttons were scoped as Friend.
I've always wondered why controls dropped from the toolbox weren't scoped to Private by default.
I think your problem is that the default values for the Anchor property is not to be anchored. When you change the property and compile, that doesn't mean that's the default setting for classes that inherit your control.
If you are using the property selector, Visual Studio automatically puts some code in your application to change those values (i.e the designer code). Find the InitializeComponent() method and I bet you'll see something to the effect of:
this.myOKButton.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
this.myCancelButton.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
You'll need to set this property somewhere in your class, like the constructor, or override that property and specify the way you want it anchored.

Resources