C# WPF - Switching between Grids - c#

i am almost new to C# with WPF. I have a small problem. Maybe the solution is very easy, but i don't see it right now. So i want to make different TABLES. I use Grids to make my own table. Now i want to switch between the tables at different states of my application, so that i make a grid invisible and the one i need visible. How do i implement several grid tables in XAML? For example i have a tabcontrol and in the tabitem i want to place more than one grids, but thats not possible. I tried using StackPanel for example but then i have a gap at the bottom of the grid. I need a way to define several grids and switch between them. Before C# i worked with MATLAB and i just put every table in a PANEL and switched them visible and invisible when i needed them. Is there no similar way in WPF?
Greetings

In such cases, i would go with UserControls. One usercontrol for each grid type. A sample (not related to Grid in question) would be like the below.
<Window.Resources>
<ResourceDictionary>
<DataTemplate x:Key="DTGlobalAdminManager">
<AC:UCGlobalAdmin DataContext="{Binding Source={x:Static GVM:VMAdminConsole.Instance}, Path=ViewModelGlobalAdmin}"/>
</DataTemplate>
<DataTemplate x:Key="DTCompanyAdminProjects">
<AC:UCCompanyAdmin DataContext="{Binding Source={x:Static GVM:VMAdminConsole.Instance}, Path=ViewModelCompanyAdmin}" />
</DataTemplate>
<DataTemplate x:Key="DTProjectAdminManager">
<AC:UCProjectAdminManage DataContext="{Binding Source={x:Static GVM:VMAdminConsole.Instance}, Path=ViewModelProjectAdmin}"/>
</DataTemplate>
<DataTemplate x:Key="DTGlobalAdminAssignCategories">
<AC:UCGlobalAdminCategories DataContext="{Binding Source={x:Static GVM:VMAdminConsole.Instance}, Path=ViewModelGlobalAdmin}"/>
</DataTemplate>
</ResourceDictionary>
</Window.Resources>
You can set up a content control and different usercontrols (each containing different grid template). Then switch them using a Style Trigger.

Related

UserControls not rendering

Okay, to start, I'm pretty inexperienced with WPF and XAML, so any pointers or advice would be greatly appreciated.
I have a scheduling program that I'm working on that I need some help setting up. I had things working previously, but it wasn't organized correctly. I had UI elements in my ViewModels that I would add to a StackPanel at the initialization of the MainWindow. Generally not MVVM style coding. So I made some views (UserControls) to display the things I have, and most everything broke.
Basically, I have a Schedule ViewModel that has some parameters and a list of a different Room ViewModels. Each Room ViewModel has a RoomSchedule ViewModel that contains a list of RoomEvent ViewModels.
I'm trying to write controls for the things that need displaying. I've created a Schedule view, which has a list box of Room views, and the Room view uses the RoomEvent view to display the events of the room. The Room view uses the WPF Extended Toolkit's TimelinePanel, the rest of the controls are pretty much basic controls. The general idea has been: a model provides data to the ViewModel, which massages that data to what needs to be displayed. So an Event should know how to display itself, a Room should know how to display itself, and the Schedule should know how to display itself.
The problem I'm running into is: now that I've scooted everything from the xaml.cs or ViewModel files to their appropriate places, the controls aren't rendering at all. I've been reading other SO postings where people have the same problem, but none of them seem to work for beginner stuff like this. I think I'm close, it seems like all the controls are being created, and the DataContext's are being set correctly, but nothing is showing up.
This is, basically, what I have so far. I left some of the xaml boilerplate stuff off for succinctness:
Schedule.xaml:
<StackPanel>
<ListBox ItemsSource="{Binding Rooms}" >
<ListBox.ItemTemplate>
<DataTemplate>
<localcontrols:RoomView ScheduleStart="{Binding ElementName=ScheduleControl, Path=DataContext.Start}"
</DataTemplate>
<ListBox.ItemTemplate>
</ListBox>
</StackPanel>
RoomView.xaml:
<extended:TimelinePanel BeginDate="{Binding localcontrols:ScheduleStart}" EndDate="{Binding localcontrols:ScheduleEnd}"
<ItemsControl ItemsSource="{Binding Path=mRoomSchedule.mScheduledEvents}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<localcontrols:EventView />
</DataTemplate>
</ItemsControls.ItemTemplate>
</ItemsControl>
</extended:TimelinePanel>
EventView.xaml:
<Border BorderThickness="1" BorderBrush="Black" extended:TimelinePanel.Date="{Binding mStartTime}" extended:TimelinePanel.DateEnd="{Binding mEndTime}">
<TextBlock Background="{Binding mColor}" Text="{Binding mEventID}" />
</Border>
The ScheduleStart and ScheduleEnd are dependency properties defined in RoomView.xaml.cs. My thinking was that Schedule would have Start and End properties that would be set in its constructor, and the RoomViews in the ListBox would bind to those properties to set the TimelinePanel's BeginDate and EndDate.
Maybe your bindings are wrong. When I need to bind to a dependency property I use the ElementName feature of binding to say which control I want and I give the root node a name, in this case Root. It's one way to solve it.
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Weingartner.Controls"
x:Class="RoomView"
x:Name="Root">
<extended:TimelinePanel
BeginDate="{Binding ElementName=Root, Path=ScheduleStart}"
EndDate="{Binding ElementName=Root, Path=ScheduleEnd}"
>
<ItemsControl ItemsSource="{Binding Path=mRoomSchedule.mScheduledEvents}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<localcontrols:EventView />
</DataTemplate>
</ItemsControls.ItemTemplate>
</ItemsControl>
</extended:TimelinePanel>
</UserControl>

Control not inheriting datacontext from parent?

Is there any reason for a control not to inherit the datacontext from its parent?
I've inherited a rather ugly piece of WPF code, which I've been tasked with updating. I want to change some text blocks from being hard coded strings to data bound values.
The basic layout I've got is
<Grid>
<TextBlock Text="The Caption" />
</Grid>
which I've changed to
<Grid>
<TextBlock Text="{Binding BoundCaption}" />
</Grid>
However when I run the application, the textblock is blank.
Using WPF Snoop I can see that the grid has the expected datacontext (the view's viewmodel), but the datacontext of the textblock is null. If it makes any difference, the grid is actually used in a C1TabItem header (Component One library), so the visual tree is a mass of borders, content presenters, layout rounders etc. So far as I can tell there are no styles defined in the application for textblock.
I know I can get around this by directly setting the datacontext of the textblock explictly using
DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type Grid}}}"
but this ugly hack shouldn't be necessary.

stackpanel with usercontrol and itemsource shows newitemplaceholder

Im about to create a diagram designer, and have create nodes and edges as usercontrols.
I have an stackpanel where I want to place them. I have managed to make it works with the following code:
<Window.Resources>
<DataTemplate DataType="{x:Type Model:Node}">
<Canvas>
<View:NodeUserControl></View:NodeUserControl>
</Canvas>
</DataTemplate>
</Window.Resources>
<StackPanel Name="DisplayArea">
<ItemsControl ItemsSource="{Binding Nodes}" >
</ItemsControl>
</StackPanel>
Where Nodes is an observablecollection
But this also shows an {NewItemPlaceholder} text and I can't figure out why. Would really appreciate if someone could point out my mistake.
EDIT: I have tried to create a new solution with just the beforementioned code and this doenst show the [NewItemPlaceholder}. Now Im really confused can't see the difference and what else that would cause this.
I got the same issue and the cause was that die source data was bound twice: One time to a DataGrid control and a second bound to an ItemsControl. The ItemsControl shows its items on a canvas and also {NewItemPlaceholder} becomes visible there.
The solution was to avoid adding new items to the DataGrid by:
ok. I didn't need adding.

Same XAML but different code behind for user controls

I have 3 user controls in WPF which have the same layout (a few buttons and a listview) but the code in behind is different because the listviews list collections of different classes.
Is it possible to somehow use the same XAML for the three usercontrols? Because right now, if I make a change to the layout of one XAML I have to do it for the other two manually.
Thanks
That's perfect scenario for MVVM
Create a single UserControl or View
Create three different backend classes which will act as ViewModel
For each instance of UserControl use different ViewModel as DataContext
1) Extract common XAML into the separate XAML file and then in target control's use it as DataTemplate:
<!-- 1. CommonView.xaml would contains common XAML -->
<!-- 2. Below is XAML of the any of three control -->
<UserControl>
<!-- In three controls use shared XAML as data template -->
<UserControl.Resources>
<DataTemplate x:Key="sharedTemplate">
<views:CommonView />
</DataTemplate>
</UserControl.Resources>
<MyControl>
<ContentPresenter ContentTemplate="{StaticResource sharedTemplate}" />
</MyControl>
</UserControl>
2) Bind each of the control to a separate ViewModel

Multiple grids in one area

I'm currently creating a WPF application, using C# and XAML in Visual Studios 2010.
I have a master grid. In that master grid I have a group bar which you can select different items. Depending on what you select, the middle of the master grid can be totally different. What I was wondering is, what's the best way to program the middle part?
Right now, I have it set up in such a way that everything in the middle is dynamically programed in C#, and everything on the outside is programmed in XAML.
In C# I programmed: for each group bar item, there is a grid that goes with it (so that different content can be displayed on it). Each grid is a child of the master grid. Each grid is visible or hidden when necessary. Is this the best way to approach this?
The best example of this is in Outlook 2007, where you have your group bar on the right hand side. When you select different items on the group bar (mail, calendar, tasks) the right of the group bar completely changes.
The easy way to do this in WPF is to define DataTemplates for each of your "middle" sections.
Using the Outlook example, you might have a MessageCollection class that stores a list of messages, an EventCollection class that stores a list of calendar events, and a TaskCollection class that stores a list of tasks.
In your "middle" area you would simply have a single ContentPresenter whose Content would be set to a MessageCollection, EventCollection, or TaskCollection. Presumably this would be done using a binding to a view model property.
Here is how it might look:
<Window ...>
<Grid>
<!-- group bar area -->
...
<!-- "middle" area -->
<ContentPresenter Grid.Row="1" Grid.Column="1"
Content="{Binding SelectedCollection}" />
</Grid>
</Window>
Now you create a DataTemplate for each of the collection types, for example:
<DataTemplate TargetType="{x:Type my:MessageCollection}">
<Grid>
... put the XAML for displaying mailbox contents here ...
</Grid>
</DataTemplate>
<DataTemplate TargetType="{x:Type my:EventsCollection}">
<Grid>
... put the XAML for displaying a calendar here ...
</Grid>
</DataTemplate>
<DataTemplate TargetType="{x:Type my:TasksCollection}">
<Grid>
... put the XAML for displaying a to-do list here ...
</Grid>
</DataTemplate>
With this setup, all you have to do to switch the inner grid is to set your "SelectedCollection" property in your view model to a different collection type.

Categories