We have a "legacy" WPF applicaton that is based on a NavigationWindow. The NavigationWindow has a fairly large ControlTemplate that houses a ContentPresenter as so:
<ControlTemplate>
....snip...
<ContentPresenter x:Name="PART_NavWinCP" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
.....snip....
</ControlTemplate>
What we want to do is use that ContentPresenter as the first tab and dynamically add other tabs at run time. Like this:
<ControlTemplate>
....snip...
<TabControl Background="Transparent" cal:RegionManager.RegionName="MainRegion" Grid.ColumnSpan="2" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<TabItem Header="Nav Window Content">
<ContentPresenter x:Name="PART_NavWinCP" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
</TabItem>
</TabControl>
.....snip....
</ControlTemplate>
Then our Modules grab the RegionName and insert their content dynamically. The issue seems to be that the PRISM region manager doesn't like that our code is in a ContentTemplate and cannot resolve the region. I have tried updating the RegionManager, adding the Region dynamically, just having a root tab control without the ContentPresenter, but I cannot get this to work. Any ideas?
Regions in templates are an issue - since templates are rendered after the initial content they arent 'controls' or even instances per-se and the region manager has no way to get handle on it. i would assume adding a region this way wouldnt be supported.
Now, staright up tab control w/ no templates I was able to get to work just fine but recall needing to write a content adapter that knew how to handle the target region type and registering that in the bootstrapper before i did the module loading.
So we got around this by chaning the NavigationWindow to a Frame and dropping the content in the frame. We need to do a bit of styling in order to make it look good; however, this is the only way to get around the use of a region in a NavigationWindow content template. We are now removing all code from the frame that was common to the app and will be needed by the Shell (since the NavigationWindow cannot become the Shell).
Related
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.
How can I be able to place buttons over windows border.What I am trying to do is to place close and minimize buttons over the border in a WPF application in c#.Any one could please tell me how to do that.
The word 'Border' in the context of WPF may have two meanings. It may be the <Border> element, or it is possible you mean the area the defines the <Window> element. Which one is it?
If you just want to have a buttons on a <Border> element, just put it as the content of the element. If you have more than one buttons, you need to have a panel (e.g. <StackPanel>).
You cannot draw anything beyond the client area of a <Window> element. To have buttons outside the Window area, you should another Window (say 'toolwindow') with the buttons that you want. Most likely you want this toolwindow without caption and non resizable border: WindowStyle="None" ResizeMode="NoResize". Then, keep the tool window position in sync with your main window (best thing would be to bind the Left and Right properties of both Windows to Left and Right properties in a common data context. Don't forget to declare the Binding mode to BothWay).
EDIT (follow clarification from #Sarita):
So it is the first. By Content I meant the body of the XML element. Technically, it is the Child property of the Border element. The following two XAMLs are equivalent:
<Border Background="Green" Padding="5">
<StackPanel>
<Button>A</Button>
<Button>B</Button>
</StackPanel>
</Border>
<Border x:Name="Bord" Background="Green" Padding="5">
<Border.Child>
<StackPanel>
<Button>A</Button>
<Button>B</Button>
</StackPanel>
</Border.Child>
</Border>
sorry if this question is overly simple, but I'm having a hard time figuring out how to create backgrounds to controls - in the hopes that it will improve app performance.
I have 9 different controls. All of them have a background. The backgrounds are made up of either images, other controls or both. All of those backgrounds have another background.
Think of this like Power Point with slides, slide layouts and slide masters - inherited in that order. I have 9 slides / controls.
The first 3 controls have the same "control layout" (let's call it
ControlLayout1). ControlLayout1 gets some of it's elements from ControlMaster1.
The second 3 controls also have the same control layout, but it is
different from the first. Let's call it ControlLayout2. It also
inherits from ControlMaster1.
The final set of 3 controls are different again. We can call them
ControlLayout3. But this time, they inherit from a different master - ControlMaster2.
Right now in each control I'm writing out all the XAML each time separately. I'm thinking there must be a way to not write these in each of these each item. Ideally, what I would like to create is one set of XAML that can be reused.
Here's some pseudo-XAML:
<UserControl x:Name="Control1">
<MyBackground (ControlLayout1)/>
</UserControl>
<UserControl x:Name="Control2">
<MyBackground (ControlLayout2)/>
</UserControl>
<UserControl x:Name="Control3">
<MyBackground (ControlLayout3)/>
</UserControl>
And then somewhere for ControlLayouts (I don't know, like Application.Resources or elsewhere)
<Canvas x:Name="ControlLayout1">
<MyMasterBackground (ControlMaster1)/>
</Canvas>
<Canvas x:Name="ControlLayout2">
<MyMasterBackground (ControlMaster1)/>
<TextBox Text="The Control 2">
</Canvas>
<Canvas x:Name="ControlLayout3">
<MyMasterBackground (ControlMaster2)/>
<TextBox Text="The Control 3">
</Canvas>
And then for the ControlMasters
<Canvas x:Name="ControlMaster1">
<Canvas.Background>
<ImageBrush ImageSource="/Images/image1.jpg" />
</Canvas.Background>
</Canvas>
<Canvas x:Name="ControlMaster2">
<Canvas.Background>
<ImageBrush ImageSource="/Images/image2.jpg" />
</Canvas.Background>
<TextBox Text="Control Master 1">
</Canvas>
Once defined, the ControlLayouts and ControlMasters never need to change - they are static.
Beyond just having a smaller XAP if I can put these all in one location and reuse the XAML, I'm hoping performance will be improved in my app as the ControlLayouts automatically get BitmapCached or something like that.
So first, is there a good strategy to implement the above (the ControlLayouts and Masters do not have any code-behind)? Secondly will performance be improved in loading of Control1, Control2, etc.? Finally, if they were pure usercontrols (i.e. they had some code behind), would that be better for performance?
Thanks in advance!
What you ask for is a combination of a few things:
About the Background thing: just create a dependency property (let's call it MyBackgroundDP) of type Brush in the code behind of a UserControl, and bind it to your XAML like:
<UserControl ...>
<Grid Background={"Binding MyBackgroundDP, RelativeSource={RelativeSource Mode=FindAncestor, AncestoryType=UserControl}}">
<!-- More XAML declarations -->
</Grid>
</UserControl>
To create the dependency property, you can use the built in snippet in visual studio: propdp
Simply write "propdp" and that TAB twice. Fill up the fields and it's all good.
Alright so that was easy enough, right? ;)
Now the tougher part: making so-called master pages.
Actually it's not that much different from the background thing.
Declare another dependency property, only this time of type object, or FrameworkElement (better).
Then in your XAML, you declare a kind of placeholder: ContentControl. Let's call it MyContentDP for this example:
<UserControl ...>
<Grid Background={"Binding MyBackgroundDP, RelativeSource={RelativeSource Mode=FindAncestor, AncestoryType=UserControl}}">
<ContentControl ContentTemplate="{Binding MyContentDP, RelativeSource={RelativeSource Mode=FindAncestor, AncestoryType=UserControl}}" />
</Grid>
</UserControl>
You can then fine tune whatever else you want to provide in this "master view", add a border around the Grid, put some flowers, you name it.
Once you're done, this is how you use it, assuming it was called MyUserControl
<Window ...
xmlns:local="...reference_to_your_usercontrol_dll/exe">
<Grid>
<local:MyUserControl MyBackgroundDP="Red">
<local:MyUserControl.MyContentDP>
<!-- More XAML declarations here -->
</local:MyUserControl.MyContentDP>
</local:MyUserControl>
</Grid>
</Window>
Now the performance point:
If you put all the XAML for this as a Custom control (which is DIFFERENT from a UserControl), you can then put all the XAML in your App.xaml
Why? because parsing XAML can be an intensive operation, and if you make WP7/SL parse it at runtime whenever you need it, you lose performance.
Instead, your App.xaml gets parsed at startup, then it's in memory. That's what's done in the loading of your application. You would get a performance boost, although it would be minimal for controls made of few XAML, it is still a good practice.
Hope this helps,
Bab.
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.
In Windows Forms the default behaviour of a TabControl is to have the tabs spill out to a scrollable area if they consume too much space (MultiLine = false).
What is the best approach to achieving this behavior in WPF?
UPDATE
I was trying to find a solution using TabControl.ItemsPanel but it seems anything I put in there gets completely ignored, so for this reason I've gone the hard way and started with TabControl.Template which is mind boggling that we have to do it this way if it turns out to be the correct approach.
Extremely far from being complete, my starting solution to the problem is as follows.
<TabControl>
<TabControl.Template>
<ControlTemplate TargetType="{x:Type TabControl}">
<DockPanel>
<ScrollViewer DockPanel.Dock="Top"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Disabled">
<StackPanel Orientation="Horizontal" IsItemsHost="True" />
</ScrollViewer>
<ContentPresenter ContentSource="SelectedContent" />
</DockPanel>
</ControlTemplate>
</TabControl.Template>
<TabItem Header="One">First</TabItem>
<TabItem Header="Two">Second</TabItem>
<TabItem Header="Three">Third</TabItem>
<TabItem Header="Four">Fourth</TabItem>
<TabItem Header="Five">Fifth</TabItem>
</TabControl>
In working to make a TabControl where the tabs are stacked vertically along the left, I found this solution for you:
http://www.blogs.intuidev.com/post/2010/02/10/TabControlStyling_PartThree.aspx
Pretty impressive stuff!
Your solution to replace the template seems to be the best way to do this. The default panel for the TabItems is a TabPanel, and I don't see anything like a "should wrap" property on it.
The documentation contains an example of replacing the TabControl template with a different TabPanel:
http://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.tabpanel.aspx
i had the same problem few years ago, my solution was to limit the size of the header, and the panel that contains it, of course you need to make your own template like what you started, and also i need to implement some scrolling support so i put two repeat buttons at the left and right side of the scroll viewer.
my inspiration was a nice project from code project called IE tabs in wpf.
it's old as wpf and works good
I know this is an older post, but I wanted to add another idea should others be searching this on the internet.
If you set the width of the tabpanel to something larger it will be (assuming this is not a tabpanel that allows the user to continue to add other tabs in it). If you have the user adding new tabs to the tab panel, then a scroll bar will need to be added.
the easiest option is to set the ItemsPanelTemplate on the TabControl. I think the default is WrapPanel, hence the Multiline behaviour.
Change it to StackPanel for example and maybe add a ScrollViewer.
Something like this (just coding this without VS)
<TabControl>
<TabControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</TabControl.ItemsPanel>
</TabControl>
hope that helps a bit...