As a new comer to WPF, I would like to clarify my approach to build a UI in WPF. I am using WPF with MVVM. My approach is to use a main window which contains user controls which can run several levels deep in the UI tree. For example, I have an editor in a window. Many items can be edited in the editor and the UI for each items are different, but the editor always shows an OK and Cancel button. So the main editor window with OK and Cancel can be shared between several editors. I am designing the app in such a way that the editor user control will just bind the view model for the item which is edited. So when designing the UI for editing individual items OK or Cancel Button is not pulled in, but simply put the item into the main editor which will provide the buttons. I am pretty sure I can handle the commands correctly with WPF command infrastructure.
If I can make it clear with some xaml here it is.Please dont mind the control placement itself, I mean to explain the basic idea of sharing the Common UI across many items.
<UserControl Name="EditorMainWindow">
<Grid>
<StackPanel>
<ItemsControl ItemsSource="{Binding ItemToBeEdited}">
</ItemsControl>
<Button Content="OK" Width="120" Command="{Binding SomethingforOK}" />
<Button Content="Cancel" Width="120" Command="{Binding SomethingforCancel}"/>
</StackPanel>
</Grid>
</UserControl>
The way I am doing it, the user interface tree can go several levels deep. I will be tremendously benefitted, because if the client ask to change the UI in one particular place, I need not got and change it in many places(provided it is shared).
As I am new to WPF I would like to know if there is any catch in this approach. Could you please tell me if this makes sense or not?
You can save yourself a lot of time. Catel already provides such a window:
DataWindow
It is fully ready for MVVM (Catel is also an MVVM framework) which supports dynamic nested user controls. The nice thing is that it also supports error handling out of the box, so as soon as an error occurs in the window template, the user will see the error in the InfoBarMessageControl.
Related
I'm using Catel in my application and I have problem with changing screens.
I have a ribbon navigation and a ContentPresenter for a screen. When I click ribbon button, I change ActiveView property in my ViewModel
It looks like this:
<ContentPresenter Margin="5 5 5 0" Content="{Binding ActiveView, Converter={StaticResource ViewModelToViewConverter}}" />
ActiveView is a ViewModel of my UserControl for specific view.
The problem is, that everytime I change screen (click ribbon button), I have a lag ~100ms which is very irritating.
I have also tried with DataTemplates for ContentPresenter, but there is no Performance boost with it.
Is there a way of boot performance of this? Maybe a way to pre-construct view, and then only show it? (because right now View is being constructed everytime I click a ribbon button)
Of course I'm checking it on Release build (on debug there is much more lag) :)
Please check the performance considerations in the docs. A few hints:
Have you tried without a debugger attached?
Are there log listeners doing a lot of work?
Enable Api cop to see what features you are not using but are taking time. Then you can disable them.
Probably it's the control looking for the InfoBarMessageControl (which you can simply disable).
I was able to add an item using the Window Handler and such, but I also want to remove the already existing items (the window tool window inside of our main app, and we don't want all those options there). In the screenshot below it shows the one I added and the ones I want to remove (pretty much all of them). Let me know if there's a way to do this.
EDIT:
Or better yet, how to put my own context menu with XAML (if possible). But I don't want to lose the title bar or the aero effect.
Thanks!
I know this answer is slightly different than what you are asking, but it may help. You are wanting to modify the built-in menu from the window title bar... but what if you overlay that menu with your own using custom chrome (like how mozilla firefox/MS Office does it)?
To do this, download WPF Shell Integration Library from http://archive.msdn.microsoft.com/WPFShell and play around with it. The library also includes a few other cool features like jump lists.
more documentation on this technique is at http://blogs.msdn.com/b/wpfsdk/archive/2008/09/08/custom-window-chrome-in-wpf.aspx
You can create your own ContextMenus in WPF
<Grid>
<Grid.ContextMenu>
<ContextMenu>
<MenuItem Header="Dock" Command="{Binding ...}" />
</ContextMenu>
</Grid.ContextMenu>
</Grid>
Just be careful with the Bindings because WPF ContextMenus are not part of the same Visual Tree as the rest of your controls, so bindings do not work as expected. You will probably need a relative source binding to the PlacementTarget to get your command.
(I am trying to learn WPF using tutorials and documentation, and trying to develop a user interface for my backend-complete application while I do say. I've heard people say that the learning curve is quite steep. But sometimes I wonder whether what I'm trying to do is actually something that's hard to do in WPF, or if it's simple but I'm thinking in wrong terms, or if it's neither, it's quite simple but I just happen not to know how.)
Here's my current question. I wanted clicking that clicking some part of my UI will bring up a 'popup' where the user can enter more information. I would like a 'lightbox-style' popup, i.e. the popup is modal to the page, it darkens the rest of the page to become the center of attention, etc. These are seen commonly on Web sites.
A bit of searching led me to the WPF Popup control. I added it, put my content in, set the IsOpen property to True, and -- presto! A popup. Then I added an invisible Rectangle that covers my whole window, and set it to Visible as well when I want my popup to open. Great!
So now I wanted to do this dynamically, because sometimes I will be loading a record which will sometimes have a need to open another control (a UserControl) in a popup to edit its information. So I made myself a method called OpenPopup. But I can't seem to find a way to write this method using WPF. In Windows Forms I'd have written: (I use VB.NET)
Sub ShowPopup (form as Form, ctrl as Control)
'Create 'rect' as new dark rectangle control
'Z-order it to the top
'form.Controls.Add 'rect'
'form.Controls.Add ctrl
'Z-order 'ctrl' to the top
'Center 'ctrl'
'Set focus to it
End Sub
But with WPF I run into problems:
1) I can't add it to the WPF window, because it already has a child.
2) If that child is a Canvas, that's not too bad. I can detect that, and add it to the Canvas. I have to find some way to set its Left, Top etc. properties and Width and Height, since those do not seem to be properties of the Rectangle control but rather extended by the Canvas object -- in XAML they're called Cavnas.Top etc. but Intellisense is not showing them when I try to use it in code.
3) But if it's a StackPanel? Then my rectangle will just be stacked below the other controls! And not covering them! Is there a way around this?
4) And if the window contains only one control and no container control at all?
5) I think there were more problems I ran into. But let's start with these.
Thanks in advance for your help.
1) I can't add it to the WPF window, because it already has a child.
Ah, the evils of codebehind. The solution is not to add it to the visual tree, it is to place it in the visual tree, ready and waiting to pounce, but hide it from the user's view.
Here's a sample you can drop in Kaxaml that demonstrates the point. Set the Lightbox Grid's Visibility to Hidden to access the hidden content.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Viewbox>
<TextBox Text="SIMULATING CONTENT" />
</Viewbox>
<Grid x:Name="Lightbox" Visibility="Visible">
<Rectangle Fill="Black" Opacity=".5"/>
<Border
Margin="100"
Background="white"
BorderBrush="CornflowerBlue"
BorderThickness="4"
CornerRadius="20">
<Viewbox Margin="25">
<TextBox Text="SIMULATING LIGHTBOX"/>
</Viewbox>
</Border>
</Grid>
</Grid>
</Page>
2) (snip) Intellisense is not showing them when I try to use it in code.
Canvas.Top etal are Attached Properties. Attached Properties are extremely convenient and easy to use in XAML, but they are very confusing and hard to use from code. Another reason why codebehind is evil.
3) But if it's a StackPanel? Then my rectangle will just be stacked below the other controls! And not covering them! Is there a way around this?
I redirect you back to 1. There are also many other container controls in WPF. You should investigate them and observe how they control layout. For instance, my use of the Grid was not to make use of its ability to block off sections of UI for controls, but for its ability to layer controls ontop of each other and to stretch them out to their maximum available size for the available space (the viewboxes are just there to zoom the controls instead of stretch them).
4) And if the window contains only one control and no container control at all?
The root of a window would almost always be a container control. But you control that, so if you needed to add controls to the visual tree at runtime you could easily ensure the child of the window is a container control you could deal with.
5) I think there were more problems I ran into. But let's start with these.
No kidding. My number one suggestion for people in your situation is to drop what you're doing and learn about MVVM. The Model-View-ViewModel is a very simple way to code WPF applications that takes advantage of many of the features of WPF--databinding, templating, commands, etc. It allows you to code your logic not in codebehind (RETCH) but in easy to create and test classes.
I want to create a custom dialog box-like control in Silverlight for WP7 that I can use this way:
<local:Dialog>
<StackPanel>
<TextBlock>Are you sure?</TextBlock>
<Button Content="Yes" Click="ClickCallback" />
</StackPanel>
</local:Dialog>
As in, just a simple container that I can add arbitrary content to. I just want to add storyboards for animations and a backdrop to make the dialog modal, etc. I already have this ready.
What I don't know how to do is add the content. I've read that you have to inherit from ContentControl, but how is this actually implemented?
There are number of good examples on ContentControl usage available in Silverlight Toolkit. For example Frame control located in Source\System.Windows.Controls.Navigation\System\Windows\Controls\Frame.cs
Greetings
I'm currently making an application in WPF as I'm fairly new to WPF I'm running into some difficulties. I have Googled my question but with no great success. This is the current situation, XAML of main window below:
<Grid Height="279" HorizontalAlignment="Left" Margin="166,0,0,0" Name="gridScoreboard" VerticalAlignment="Top" Width="808">
<!--Scoreboard Image-->
<Image Source="pack://application:,,,/Images/Style/Scoreboard.png" Width="517" Height="91" HorizontalAlignment="Left" Margin="138,1,0,0" Name="image1" Stretch="Fill" VerticalAlignment="Top" />
<Canvas Name="canvasRacePlayer1" Width="14" Height="14" Canvas.Left="33" Canvas.Top="66" Background="Transparent" MouseLeftButtonDown="canvasRacePlayer1_MouseLeftButtonDown" Margin="171,70,623,195" />
<local:ucRaces HorizontalAlignment="Center" Margin="93,62,632,187" Width="78" Visibility="Hidden" x:Name="ucRacesP1" Height="33" />
</Grid>
The user control is hidden from the start (ucRaces), once the little canvas (canvasRacePLayer1) is clicked the user control will be shown. However I would like this user control to 'slide' from right to left from a certain point. As if it would become visible in small steps. I have found information for animations for rectangles and buttons but no success really for User Controls.
Thank you in advance
If you are going to create animations for your WPF project, I suggest that you use Expression Blend. You can design your program using EB and implement the functionality of it using Visual Studio. It will be hard to make animations, writing XAML syntax or C# code.
How would you be able to animate your user controls using EB? Well, it is actually very simple. You need to open your existing WPF project first. Then, go to File -> New Item -> User Control, and create the user control. Then, if you want to add it to your project, switch back to the WPF project currently open in EB and click the right arrows (>>) on the toolbar placed on the left-hand side of the screen and go to Project -> [Your User Control Here]. Now you have added it to your project.
If you want to animate the user control, you have to add a StoryBoard to your timeline. When you are on your WPF project in EB, under Objects and Timeline, click the plus (+) sign and add a new StoryBoard. Now, you have a timeline that you need to use to animate your user control. You can place KeyTime attributes on the timeline and define the path the user control is supposed to follow from location A to location B and also the level of opacity if you want the user control to gradually become visible.
You can add one more user control and implement its logic for the second user. Expression Blend will make your life easier.
Animating your UserControl shouldn't be much different from animating any other WPF object: You can either animate the margin (using a ThicknessAnimation), or drop your user control into a canvas of its own, then animate the Canvas.Left property of your user control. In the latter case, take care to put the property name in parenthesis: Storyboard.TargetProperty="(Canvas.Left)".