WPF Windows to Tabs - wpf

I have an already made WPF application which is Windowed based and now I wish to implement tabbed controls instead of each of those separate windows. What would be the easiest and fastest way to reuse?
Thanks

Typically when I want to convert, I take the contents of each Window (which is usually wrapped in a Grid) and I convert them to a UserControl. You can basically move the entire Xaml and code-behind almost as-is, with only minor tweaks.
You then replace your Window contents with the UserControl, and you can reuse the same UserControl in a tab, or anywhere else.

Or you could convert you Windows to Pages and create frames in the tabs and put the page in the frame. It might be easier convert you Windows to Pages (and it might not) - depends on your Windows. I like the UserControl answer. Just putting another possilble option out there.
<TabItem>
<TabItem.Header>
<TextBlock Style="{StaticResource TabItemHeader}">DocTxt</TextBlock>
</TabItem.Header>
<Frame Source="PageViewDocText.xaml" BorderThickness="0" Margin="0"/>
</TabItem>

Transfort all your windows into UserControl and build your new window with your TabControl.

Related

Create/Modify new WPF UI components

I want to change the graphical UI elements in WPF.
For example, I want to use a kind of a stack panel, but on the other hand I want to show my details in a star, or circle, etc.
Maybe setting a bitmap as a background, but I am working with lots of Data using zoom tool.
I found tutorials, documentation only for changing attributes of "old components", but nothing to make new ones.
Great resource for WPF beginners is www.wpftutorial.net
One of the best idea of WPF is separation of concerns:
UI Control = Logic in Code/XAML + Template
Using templates in XAML we can vary representation without modifying the control.
For example, if there is a need in creation of list of items. Then we can use ListBox control:
<ListBox>
<ListBoxItem>USA</ListBoxItem>
<ListBoxItem>UK</ListBoxItem>
</ListBox>
By default LisboxItem internal part is just binded TextBlock.
Now making UI modification without changing control source code:
<ListBox ImageSource="{Binding PathToSource}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource ProjectIcon}"/>
<TextBlock Text="{Binding Path=PropertyName}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
there appears image and text.
If there is a need in creating exclusive control then you can always use Custom Control.
Using raster images (e.g. PNG) is not good point, especially with zoom behaviour. If it is possible better to use vector images, that can be created in XAML or imported from SVG.

How can I switch Telerik ribbonview elements according to the type of my child viewmodel?

I'm using an MVVM pattern for my WPF application. If the "home" view model, which controls the layout of my application's main window, I have a ChildViewModel property. This holds a viewmodel that can be switched according to what the user is doing. When they select menu items, the child view model switches and the main area of the screen (it's in an Outlook style) switches accordingly.
I do this with a ContentControl and DataTemplate like this: (I'm only showing one of the embeddable views here to keep it short).
<ContentControl Grid.Row="1" Grid.Column="1" Margin="3"
Content="{Binding ChildViewModel}">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type vm:VersionsViewModel}">
<Embeddable:VersionsView />
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
I also want to add a ribbon to my main window, using the Telerik RadRibbonView control. I want this to have some fixed tabs and buttons that are always visible. In addition, I want to add and remove entire tabs, and buttons within existing tabs, according to the type of child view model. I'd like this to be done in the view in a similar manner to the way I've done the content control, above.
Is this possible? I've tried lots of things but got nowhere so far. I know I could do it by creating a huge "super ribbon" and binding visibility properties but this seems cludgey. I could also have multiple ribbons, each containing the common controls, but this would cause a maintenance problem.
In the end I went with the "super ribbon" approach, as I couldn't find any other way.

Embedding a ProgressBar in the TabItem header in WPF

The project I am working on generates a series of tabs for each item opened by the user. For some tabs in particular, certain database hits and calculations take an extended period of time. I was trying to determine a simple way to alert the user when the tab is ready and figured a progress bar would be as good or better than other ways I considered.
I am wondering if there is a way to embed a progress bar behind the header text of a TabItem or if I will need to build my own CustomControl. I have no clue how to do either, however, I think some examples of the latter exist in the project so I could try to figure that out through them.
You can define the layout of a TabItem pretty easily. This snippet of XAML will create a TabControl with one TabItem where the header of the TabItem has a ProgressBar with a TextBlock over the ProgressBar.
Of course, please customize this XAML to actually make it look good :-D
<TabControl>
<TabItem>
<TabItem.Header>
<Grid>
<ProgressBar Width="100" />
<TextBlock Text="Some Tab"/>
</Grid>
</TabItem.Header>
</TabItem>
</TabControl>

MVVM Command without A Button

I want to initiate a bound command, but I don't want to use a Button on my UserControl. In effect the UserControl is itself a Button. When it is clicked anywhere on its surface I want to initiate a bound command. Is there a way to give a UserControl a command?
In a side note: one command for one control and only a few certain out-of-the-box controls? This all seems a little clunky. I'm starting to think that MVVM is impractical. I can decouple my UI just fine with Interfaces and OOP. Anyway, I still have hope.
Also, I'm not willing to hack anything or use an expensive workaround. If I can't do this, I'm abandoning MVVM.
Take a look at the ICommandSource interface here: http://msdn.microsoft.com/en-us/library/system.windows.input.icommandsource.aspx. If you want a control to have a command, then your control should implement this interface. Examples of controls that implement this interface are ButtonBase and MenuItem. Hope this helps.
If your UserControl is essentially a Button, why are you writing your own UserControl instead of using the Button class?
To add more info, here's what you do:
Subclass Button, put any extra DependencyProperties that you need in there - it should be a very empty class (you could even have something like public class MyCoolButton : Button { }
Add a Style whose TargetType is MyCoolButton - don't name the style so it applies to all MyCoolButtons
Override the default Template of the style, then paste in your Xaml code. You might have to do some work here to handle the "Normal / Pushed / Disabled" states. If you're using v4.0, you can use VSM here.
I will agree with Paul Betts.
Quite often I create my own ListBoxItemContainerStyle using a button as the top container with nothing but a propertyless content presenter in it. This allows me to use the buttons functionality (like Command) without having the Windows chrome on it.
Putting it in the ListBoxItemContainerStyle also lets me make it so that when it is clicked it does not display the normal dotted border (FocusVisualStyle={x:Null}).
Are you using Visual Studio or Expression Blend to do your styling?
Additionally, some MVVM frameworks provide an interface for adding a command-ish ability to controls other than buttons. Caliburn has a pretty rich command pattern. I am not sure if it allows binding commands on non-button controls, however.
The OP asked for an example of how you could use a button control, but with the content properly filling the entire button. You can do this using the ContentAlignment properties:
<Button HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
<Button.Content>
<Grid IsHitTestVisible="False">
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="Row0" />
<TextBlock Grid.Row="1" Text="Row1" />
</Grid>
</Button.Content>
</Button>
This creates a button with two labels spaced using a Grid control. I mark the Grid to turn off HitTestVisible, as you have to decide which controls should interact like the button and which should interact like controls. For instance, you might have an embedded TextBox that you want to be clickable without clicking the button, in which case it should have HitTestVisible=True.
WPF supports layers and transparency :
Panel.ZIndex
You can create anything that supports commanding on a superior transparent layer, the size you want, to act as a button.

WPF 3.5 WebBrowser control and ZIndex

I'm trying to figure out why the control does not honor ZIndex.
Example 1 - which works fine
<Canvas>
<Rectangle Canvas.ZIndex="1" Height="400" Width="600" Fill="Yellow"/>
<Rectangle Canvas.ZIndex="2" Height="100" Width="100" Fill="Red"/>
</Canvas>
Example 2 - which does not work
<Canvas>
<WebBrowser Canvas.ZIndex="1" Height="400" Width="600" Source="http://www.stackoverflow.com"/>
<Rectangle Canvas.ZIndex="2" Height="100" Width="100" Fill="Red"/>
</Canvas>
Thanks,
-- Ed
Unfortunately this is because the WebBrowser control is a wrapper around the Internet Explorer COM control. This means that it gets its own HWND and does not allow WPF to draw anything over it. It has the same restrictions as hosting any other Win32 or WinForms control in WPF.
MSDN has more information about WPF/Win32 interop.
You are running into a common WPF pitfall, most commonly called the "The Airspace Problem". A possible solution is to NOT use the WebBrowser control, and instead go for something a little crazier - namely an embedded WebKit browser rendering directly to WPF. There are two packages that do this; Awesomonium (commercial) and Berkelium (open-source). There's a .NET wrapper for both of these.
You could SetWindowRgn to fake the overlapping area by hiding it as shown here:
flounder.com
msdn
I solved a similar issue where I was hosting a 3rd party WinForms control in my WPF application. I created a WPF control that renders the WinForms control in memory and then paints it to a bitmap. Then I use DrawImage in the OnRender method to draw the rendered content. Finally I routed mouse events from my control to the hosted control. In the case of a web browser you would also have to route keyboard events.
My case was fairly easy - a chart with some simple mouse interaction. A web browser control may have other issues that I didn't take into consideration. Anyway I hope that helps.
I hit this issue as well. In my case I was dragging images from one panel into the WebBrowser, but of course as soon as my image moved into the browser it was hidden.
Currently working on the following solution:
When the Image drag starts, create a Bitmap of the WebBrowser using "RenderTargetBitmap"
Add your Bitmap to the canvas, using the same width/location as the webbrowser
webControl.Visibility = Visibility.Hidden.
When the drag is released, remove your bitmap and set webControl.Visibility = Visible.
This solution is very specific to my situation, but maybe it will give you some ideas.
I managed to solve this by using this structure, check out the properties configuration in each element:
<Canvas ClipToBounds="False">
<Popup AllowsTransparency="True" ClipToBounds="False" IsOpen="True">
<Expander>
<Grid x:Name="YourContent"/>
</Expander>
<Popup>
</Canvas>
You just have to manage the Expander to show or hide your content, I'm using it for a menu bar, I think that the expander is optional depending on the case.
Check out this picture with the result, you can even show your controls on top of the WebBrowser and even outside the main window:

Resources