C#, WPF, MVVM, Creating a viewmodel for message dialogs/confirmation dialogs? - c#

I am not using anything other than a simple WPF application project in visual studio. I've implemented an mvvm application.
I want to display a list of content changes made by a user. I have a main window view model and it currently just builds a strings with changes. I have objects that I can reuse to display their properties (the content).
Currently, I use a MessageBoxResult to show a really long string with the changes. This is a terrible design (I know), but I couldn't really find an answer to what class a regular wpf project has that would allow me to achieve what I want.
I know there is a popup class I can use. In practice, which is better-- another view model for the dialog, or a popup?
Can anyone provide a simple example of one of the two approaches?
Thank you in advance for your response.

What I've done in the past is have a simple Border control, and inside of a TextBlock and whatever Button controls I need. I bind the TextBlock.Text to a public string property named "MessageBoxMessage" which calls OnPropertyChanged(). I bind the Command of each Button to a separate public ICommand which specifies what action to take in the view model when the button is clicked. I then bind the visibility of the Border control - which contains all of the other controls I mentioned - to a Visibility property.
When I want to show a dialog, I set the MessageBoxMessage to the message I want to show, makes sure the commands are set properly, and then set the Visibility on the Border to Visibility.Visible. This shows the box (border), message, and buttons.
You can even implement a semi-transparent rectangle underneath the border (over the rest of the form) that you set to visible at the same time. This will give you the nice "form dimmed" effect and also block the normal form controls from being clicked. A general note - for this to work, these controls need to be at the very bottom of your XAML as the z-index among controls at the same level is inferred from their placement in the XAML - lower in the code is top level on the form.
Let me know if you have any questions about implementing this if it sounds like what you are looking for.

Related

Dashboard controls in Winforms

I am working on a WinForm based applications(Yes I don't know WPF) and want's a dashboard like panels in it. Picture given below
Each panel will have a title and records from Database and some action controls. How could this be achieved? I don't want to use GridControl as I don't want to show Excel like spreadsheet here. How could this be achieved?
It sounds like you want to make a UserControl, possibly coupled with an automatic layout panel like FlowLayoutPanel.
Simply speaking, you would create a UserControl with whatever properties and events you require (i.e. in your example you might have a Title property and a Data property), and any events you need to respond to (e.g. you might have a button that you provide a wrapper event for). Then you can add the control to your existing form as you would any other standard control.
As far as displaying data in list form goes, one suggestion is to use a Panel and dynamically add Labels to it. Another idea could be just a simple Label with line breaks in the Text.

Should I be using a WPF user control? Or just a Grid?

So I have an application that is split into 2 parts - on the left there is a custom menu, on the right a grid that holds all the "content" (different screens).
It looks something like this:
Also, when the different buttons are hit, the menu on the left will fill up with different buttons (for example, if you hit the review button, the menu would become something along the lines):
Start Date
End Date
Employee
Project
...
I am pretty sure that I want each of the screens (to go on the right) to be their own user controls.
But my question is this: Should each of the menu's be user controls? This makes it a little harder to use them. Then I have to worry about having getters/setters so the main window can listen on the menu's buttons, etc.
The other option is to just programmatically add the buttons in the mainWindow, this way I can just add the listeners right in mainWindow.cs (into a grid)
Which is the better method? Or is there another method which is favoured?
The entire window can be done easily as a Grid.
The left side can just hold a StackPanel or other layout control with your buttons.
You can use a ContentPresenter to hold the content on the right. When you trigger your buttons, just change the bound content, and it will update with your appropriate user controls.
I think you might do it with a grid as Reed told. But if you will need to reuse this in another place, I think you should use a separated UserControl instead.
Maybe I'm misunderstanding you, but I would use a TabControl, with TabStripPlacement="Left".
If you need extra space on the left to display other stuff, you can override the default TabControl's ControlTemplate and add a bunch of margin space to the TabPanel inside the ControlTemplate. Alternatively, you could have the TabItem's header display differently when it is selected versus when it is not selected.

Best way to implement temporary overlays in MVVM

I'm writing an app that connects to network resources.
When the app is connecting, I want to popup an overlay with the usual spinney progress graphic and a cancel button. I have designed a ConnectProgressViewModel and matching ConnectProgressView for the overlay.
My question is what is the cleanest way to show/hide the overlay from the parent ViewModel?
A) Expose a constant ConnectProgressViewModel from my parent ViewModel, and have the ConnectProgressView bind its visibility to the ConnectProgressViewModel.IsConnecting property.
B) Expose a generic Overlay property from the parent ViewModel, and set it to a ConnectProgressViewModel when the user wants to connect. The parent View binds a ContentControl to this Overlay property and data templating takes care of the rest.
C) ?
The first seems to encapsulate the functionality more, with the app not having to care about showing and hiding the overlay, but exposing a constant ConnectProgressViewModel all the time feels wrong when it's only show occasionally.
The second seems to fit MVVM better with the ConnectProgressViewModel only being created when it's needed, but it places more functionality onto the parent, and also the generic Overlay property feels a bit weird too.
Cheers
EDIT:
I should clarify that this view does more than just show busy status. It allows cancelling/retries and selection of different network resources etc. I omitted such details for brevity which was perhaps a mistake as people are concentrating on the busy indicator.
I always just use a BusyIndicator from the Silverlight Toolkit. It does not have a cancel button, but you can probably style it to have one. The BusyIndicator has an IsBusy property that I bind to an IsBusy property on my ViewModel. If you style the control to have a button, you can add a cancel command to your ViewModel.
Edit
I just saw that this is WPF not Silverlight. I'm not sure if the WPF Toolkit has a BusyIndicator
Edit Again
It looks like the Extended WPF Toolkit has a BusyIndicator. Note, I have no experience with this.
I would go with something like your suggestion in A) and argue that you shouldn't implement something as generic like B) until you actually have that degree of flexibility as a requirement, like being able to show different overlay views.
Keep it simple!

Creating a reusable interface element in WPF

I'm developing a WPF application in C# and was thinking about implementing a custom UI element accross various windows.
I would like to have a minimized tray (only about 4px visible) that expands after clicking on an icon next to the tray. The expanded version would show all controls and would minimize when I click the icon again. I created a quick HTML concept to clarify things.
I know I could put a stackpanel and button in my application and making both of them move up when I click the button, but then I would need to duplicate the code a lot.
Though I'm experienced with C#, I'm fairly new to WPF interface development/templates, but I'm sure there has to be a way so I can use that UI element accross my application without needing to copy/paste a lot of lines of code in my form class file.
I hope someone can help me, or at least point me in the right direction.
There are three ways to customize your elements.
1 If you only need visual modifications you can use styles to change the appearance of the .net default controls. You can even override / extend the default templates.
2 If you want custom logic in a control you can create a custom control. The framework brings a lot of "primitives" to build upon. Examples are ContentControl or HeaderedContentControl. Say you want to build a custom expander control you can inherit your custom control from HeaderedContentControl which provides you with Header and Content properties and you just have to implement the toggling logic yourself.
CustomControls are a good choice if you want to build basic functionality which can be used throughout your application. They can be themed/styled depending on the use case, too (see 1).
3 If you want to compose different controls into one control you can create a UserControl. User controls are composed using XAML. Most top level controls are user controls driven by a view model.
Your case can be build using a Popup and ToggleButton or an Expander.
The decision depends on the desired behavior. If you want the opened panel to move following content down you need a expander. If you want a dropdown like functionality you need popup.
If you use a popup just bind the IsPopupOpen Property to IsChecked of the ToggleButton and set PopupStaysOpen = false to wire the button to your popup.
If you use an expander control you should create a style which can be applied to all equal expanders in your application to minimize the required XAML in each view.
How about using Expander Control?
There's a control called an Expander that is perfect for this. You'll have to style it to look like you want, however it has the functionality you want built-in.

Expose multiple command in WPF user control

A better explanation, I hope:
I have a toolbar with 3 buttons on it, all three bound to a Command (including a CommandParameter)
this toolbar is used on several screens
the xaml of the toolbar is exactly the same over all those screens
I want to remove the toolbar instance and replace it with a user control that provides 3 commands, so I can keep the bindings in each screen. The plan is to later change the toolbar functionality, but the external programming interface (namely, 3 commands) is the same.
So:
I created a user control, and created 3 sets of dependency properties for each command (OneCommand, OneCommandParameter, OneCommandTarget) so I can use these for the binding.
I moved the toolbar xaml inside the user control xaml.
I modified the bindings on the toolbar buttons to bind to the intristic user control properties
on each screen (or really, only the first for now) I replaced the original toolbar with the user control,binding the new properties to the correct commands.
The control shows, but the buttons don't work.
That's about it.
--
Original explanation - not so clear:
I have a WPF user control encapsulating a number of buttons. Previously, the control was a Toolbar with a number of buttons on it, but since I need exact the same functionality on a number of screens, I refactored the toolbar into a custom control.
However, I'd like to keep the command bindings of the original buttons.
I created 3 sets of dependency properties (XCommand, XCommandParameter and XCommandTarget) on the usercontrol.
In the user control xaml I bind the "real" buttons to those properties (each button to each set of properties).
Where I use the usercontrol, I bind the new properties to the real command bindings.
In essence, I want to keep the ICommandSource functionality for each "command" that the user control exposes. However, this dual databinding scenario doesn't seem to work, or I'm doing something wrong. :)
Is there a better way to do this? All I need is to "bridge" the commands from outside the control to the inner buttons so the Execute and CanExecute functionality remains.
I solved this. There was a bug in my RelativeSource in the internal control bindings. It works fine as expected, now.

Categories