Resize WPF application until remain only the window bar - c#

It's a way to modify the height on the window until remains only the window bar? Right now I use to set the height of the window to 0 BUT still remain some content above the window bar (that white and gray area), I want to remove this completely and leave only the window bar:
I use MVVM so binding is needed:
XAML:
Width="{Binding MainWindowWidthSize, Mode=TwoWay}"
Height="{Binding MainWindowHeightSize, Mode=TwoWay}"
C#
public void TriggerFloatingMode(object obj)
{
if (!_isFloatingModeEnabled)
{
MainWindowWidthSize = 500;
MainWindowHeightSize = 0;
_isFloatingModeEnabled = true;
}
else
{
MainWindowWidthSize = 1000;
MainWindowHeightSize = 560;
_isFloatingModeEnabled = false;
}
}

Add this code WindowStyle="None" in the Window tag and enter the following code at the bottom of the Window tag
<Window.Resources>
<Style TargetType="{x:Type local:MainWindow}">
<Setter Property="WindowChrome.WindowChrome">
<Setter.Value>
<WindowChrome CornerRadius="0" GlassFrameThickness="0" ResizeBorderThickness="2" CaptionHeight="0"></WindowChrome>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
In the above code, change TargetType="{x:Type local:MainWindow}" to the name of your window local: your window name

An easy solution with your code could be
<Window x:Class="YourWindow.MainWindow"
SizeToContent="WidthAndHeight">
<Grid Height="{Binding MainWindowHeightSize }" Width="{Binding MainWindowWidthSize }">
</Grid>
</Window>

Related

Adding a AnchorablesSource in AvalonDock using MVVM ViewModel first

I having problems adding an AvalonDock AnchorablesSource under a ViewModel first MVVM approach using Stylet.
My avalonDock XAML is as follows:
<DockingManager
Grid.Row="1"
DocumentsSource="{Binding Scl.Documents}"
AnchorablesSource="{Binding Scl.DocumentsAnchorable}"
x:Name="dockManager"
AllowMixedOrientation="True"
AutoWindowSizeWhenOpened="True"
IsVirtualizingAnchorable="True"
IsVirtualizingDocument="True"
ActiveContent="{Binding Scl.ActiveDocument, Mode=TwoWay}"
DocumentClosed="{s:Action DocumentClosed}"
>
<DockingManager.LayoutItemContainerStyle>
<Style TargetType="{x:Type LayoutItem}">
<Setter Property="Title" Value="{Binding Model.Title}"/>
<Setter Property="Height" Value="Auto"/>
<Setter Property="IconSource" Value="{Binding Model.IconSource}" />
</Style>
</DockingManager.LayoutItemContainerStyle>
<DockingManager.LayoutItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<ContentControl s:View.Model="{Binding Content , FallbackValue=#ERROR Content.title#}"></ContentControl>
</Grid>
</DataTemplate>
</DockingManager.LayoutItemTemplate>
<LayoutRoot x:Name="root">
<LayoutPanel Orientation="Horizontal">
<LayoutAnchorablePane x:Name="LayoutAnchorablePane" DockWidth="50">
</LayoutAnchorablePane>
<LayoutDocumentPaneGroup>
<LayoutDocumentPane x:Name="LayoutDocumentPane">
<!-- This is where the new windows are typically added -->
</LayoutDocumentPane>
</LayoutDocumentPaneGroup>
<LayoutAnchorablePaneGroup DockWidth="250">
<LayoutAnchorablePane x:Name="LayoutAnchorablePane1">
</LayoutAnchorablePane>
</LayoutAnchorablePaneGroup>
</LayoutPanel>
<LayoutRoot.LeftSide>
<LayoutAnchorSide>
<LayoutAnchorGroup>
</LayoutAnchorGroup>
</LayoutAnchorSide>
</LayoutRoot.LeftSide>
</LayoutRoot>
</DockingManager>
In my ViewModel I have:
public ObservableCollection<LayoutDocument> Documents {get; set;} = new ObservableCollection<LayoutDocument>();
public ObservableCollection<LayoutAnchorable> DocumentsAnchorable { get; set; } = new ObservableCollection<LayoutAnchorable>();
When I add a new normal layout to the LayoutDocumentPane as follows it works perfectly:
public void NewLayout(Screen viewModel, string title)
{
if (IsOpen(title) == true)
{
return;
}
LayoutDocument layout = new LayoutDocument
{
Title = title,
Content = viewModel
};
Documents.Add(layout);
Documents.Move(Documents.Count - 1, 0);
ActiveDocument = layout;
}
But If try and add a new Anchorable Layout (even with a know working ViewModel like this I get an error.
public void NewLayoutAnchorable(Screen viewModel, string title)
{
if (IsOpen(title) == true)
{
return;
}
LayoutAnchorable layout = new LayoutAnchorable
{
Title = title,
Content = viewModel
};
DocumentsAnchorable.Add(layout);
//DocumentsAnchorable.Move(Documents.Count - 1, 0);
//ActiveDocument = layout;
}
The error I get is:
Exception thrown: 'Stylet.StyletViewLocationException' in Stylet.dll
Exception thrown: 'System.Windows.Markup.XamlParseException' in
PresentationFramework.dll Unable to transform ViewModel name
AvalonDock.Layout.LayoutAnchorable into a suitable View name
Does anyone know why Stylet can find the relevant View then the ViewModel is used for a LayoutDocument but not a LayoutAnchorable in AvalonDock?
Edit 1:
The issue does not appear to be with the LayoutAnchorable viewmodels, as I can add them to the ObservableCollection<LayoutDocument> and they find a view just fine.
It is only a problem if I try and add a viewmodel to the ObservableCollection<LayoutAnchorable> that I get the error, so it appear to be an issue with my AvalonDock XAML.
Edit 2:
If I remove the following line from my XAML:
<ContentControl s:View.Model="{Binding Content , FallbackValue=#ERROR Content.title#}"></ContentControl>
I can add ViewModels to both by observable collections, and the windows appear in both the LayoutPane and the AchorablePane, except the windows are missing their content.
It therefore appears that I need a LayoutItemTemplate that works for anchorable windows but I can't seem to find an example.
Edit 3:
I've made a bare bones project that demonstrates the problem here if anybody wants to have a play.
https://github.com/montyjohn/StyletAvalonDockTest.git
If Stylet and AvalonDock can be made to play nicely together it would be a great starting point so new applications.
I think there is a problem with DockingManager, because it sets different DataContexts for its items. The DataContext for ContentControl is LayoutDocument for DocumentPane but it is ContentPresenter (Parent of LayoutAnchorable) for AnchorablePane.
You can use this workaround. I added a template selector and modified ShellView.xaml file. Now it works.
ShellView.xaml
<Window x:Class="StyletAvalonDockTest.Views.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ts="clr-namespace:StyletAvalonDockTest.TemplateSelectors"
xmlns:s="https://github.com/canton7/Stylet"
mc:Ignorable="d"
Title="ShellView" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
<Button Width="auto" Command="{s:Action NewLayout}">Add New Window</Button>
<Button Width="auto" Command="{s:Action NewLayoutAnchorable}">Add New Anchorable Pane</Button>
</StackPanel>
<DockingManager
Grid.Row="1"
DocumentsSource="{Binding Documents}"
AnchorablesSource="{Binding DocumentsAnchorable}"
>
<!--If the theme is removed, neither the new Layout, nor the New Anchorable Layout work-->
<DockingManager.Theme>
<Vs2013LightTheme />
</DockingManager.Theme>
<!--This adds the title to the new windows-->
<DockingManager.LayoutItemContainerStyle>
<Style TargetType="{x:Type LayoutItem}">
<Setter Property="Title" Value="{Binding Model.Title}"/>
</Style>
</DockingManager.LayoutItemContainerStyle>
<DockingManager.LayoutItemTemplateSelector>
<ts:PanesTemplateSelector>
<ts:PanesTemplateSelector.DocumentPaneTemplate>
<DataTemplate>
<ContentControl s:View.Model="{Binding Content}"/>
</DataTemplate>
</ts:PanesTemplateSelector.DocumentPaneTemplate>
<ts:PanesTemplateSelector.AnchoroblePaneTemplate>
<DataTemplate>
<ContentControl s:View.Model="{Binding Content.Content}"/>
</DataTemplate>
</ts:PanesTemplateSelector.AnchoroblePaneTemplate>
</ts:PanesTemplateSelector>
</DockingManager.LayoutItemTemplateSelector>
<LayoutRoot>
<LayoutPanel>
<LayoutAnchorablePane>
<!-- This is where the new Anchorable windows are added -->
</LayoutAnchorablePane>
<LayoutDocumentPaneGroup>
<LayoutDocumentPane>
<!-- This is where the new windows are added -->
</LayoutDocumentPane>
</LayoutDocumentPaneGroup>
</LayoutPanel>
</LayoutRoot>
</DockingManager>
</Grid>
PanesTemplateSelector.cs
using AvalonDock.Layout;
using System.Windows;
using System.Windows.Controls;
namespace StyletAvalonDockTest.TemplateSelectors
{
public class PanesTemplateSelector : DataTemplateSelector
{
public DataTemplate DocumentPaneTemplate { get; set; }
public DataTemplate AnchoroblePaneTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is LayoutDocument)
return DocumentPaneTemplate;
else
return AnchoroblePaneTemplate;
}
}
}

VisualLineElementGenerator VerticalAlignment to Center

In my application I'm using the TextEditor from Avalon.
With the following code I'm creating a VisualLineElementGenerator which works just fine:
internal class SoftwareDependencyElementGenerator : VisualLineElementGenerator
{
private static readonly Regex imageRegex = new Regex(#"<Dependencies>([ \t])*$");
private readonly Action<object> doImportAction;
public SoftwareDependencyElementGenerator(Action<object> doImportAction)
{
this.doImportAction = doImportAction;
}
private Match FindMatch(int startOffset)
{
int endOffset = CurrentContext.VisualLine.LastDocumentLine.EndOffset;
TextDocument document = CurrentContext.Document;
string relevantText = document.GetText(startOffset, endOffset - startOffset);
return imageRegex.Match(relevantText);
}
public override int GetFirstInterestedOffset(int startOffset)
{
Match match = FindMatch(startOffset);
return match.Success ? (startOffset + match.Index) : -1;
}
public override VisualLineElement ConstructElement(int offset)
{
Match match = FindMatch(offset);
if (match.Success && match.Index == 0)
{
return new InlineObjectElement(0, new AddSoftwareDependencyScriptControl(doImportAction));
}
return null;
}
}
The AddSoftwareDependencyScriptControl which is created in the ConstructElement method looks like:
<UserControl x:Class="MyApplication.AddSoftwareDependencyScriptControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Width="16" Height="16" >
<Grid>
<Button Name="btn" BorderBrush="Transparent" BorderThickness="0" Command="{Binding ShowSoftwareDependenciesCommand}" Width="16" Height="16">
<Button.Content>
<Grid>
<Image Width="14" Height="14" Cursor="Hand" ToolTip="Softwareabhängigkeit hinzufügen"
Source="pack://application:,,,/Resources;component/Graphics/Dependency.png"/>
</Grid>
</Button.Content>
<Button.Template>
<ControlTemplate TargetType="Button">
<ContentPresenter Content="{TemplateBinding Content}"/>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</UserControl>
To add the SoftwareDependencyElementGererator to the Avalon-TextEditor I just use:
SoftwareDependencyElementGenerator softwareDependencyElementGenerator = new SoftwareDependencyElementGenerator(SelectSoftwareDependency);
AvalonTextEditor.TextArea.TextView.ElementGenerators.Add(softwareDependencyElementGenerator);
Everything just works like expected. But the location of the Control is not where I want it to be.
As you can see. The control is not in the vertical center. I just tried setting the VerticalAlignment of the UserControl, the Button and the Image. Nothing worked. Also making the Image smaller doesn't affect the vertical position.
What can I do to set the Control centered, so it's exactly in one line with the text behind?
I solved it by myself.
I always tried changing the Margin at the top like
Margin="0,10,0,0" but the solution is to make the margin at the bottom negative.
My solution now is:
Margin="0,0,0,-18"

WPF - How to make Window opacity to white

I want to make the window have the effect can change the whole window which has many elements evenly to white, as the window behind in the picture:
I use code like
public MainWindow()
{
this.Opacity = 0.5;
}
but it change to black
How to make it whole evenly change to white even when there're many Element in the Window and don't set the window Style to none?(Because set Window AllowTransparent seems have to set the Style to none at the same time)
I hope can using code to do it, because I want to do it dynamically.
(Or possibly it use UserControl but not Window to achieve this effect? maybe the UserControl use with the Window and set the UserControl to Transparent can do it
----After I try, I find UserControl doesn't have property AllowTransparent, so it seems imposible use this way )
Basically, you have two options:
Use white Background color on Window and change Opacity on the window children, so the white starts to shine through
<Window Background="White">
<Grid Opacity="{Binding WhiteOutVisibility}" Background="WhiteSmoke">
<YourContent/>
</Grid>
</Window>
Use a white overlay control with alpha or Opacity that lets the actual content shine through
<Grid>
<YourContent/>
<Border Background="#80ffffff" Visibility="{Binding WhiteOutVisibility}"/>
</Grid>
In my opinion, you should use a white overlay if you want to block user interaction with the window content and white background if you want to continue user interaction.
If you need to fade only the client area, you can just put overlay - some empty semitransparent control over all the content on the window.
You can achieve this effect by laying a canvas over your window, and setting the background to white and an opacity value. Some xaml like this will work. Just change the UserControl for Window.
<UserControl x:Class="View.UserControl1"
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"
mc:Ignorable="d"
d:DesignHeight="40" d:DesignWidth="100">
<Grid>
<TextBox Text="Hello there" />
<!-- this will show faintly -->
<Canvas Background="White" Opacity="0.8"></Canvas>
</Grid>
</UserControl>
This xaml looks like this:
The Window type has property AllowsTransparency. You can find it property on your window properties in MSVisualStudio. This can solve your problem.
Thanks for Phillip Ngan and grek40 s' answer,
both Grid and Canvas with background white and opacity works,
I write some test code that can show the effect
Xaml Part
<Window x:Class="WPFAbitraryTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Button Grid.Row="0" Background="Blue" Foreground="White" FontSize="20" Click="SwitchOpacity_OnClick">Clcik to SwitchOpacity</Button>
<Button Grid.Row="1" Background="ForestGreen">hi2</Button>
<ListBox Grid.Row="2" Background="Orange">
<ListBoxItem>ListBox Item #1</ListBoxItem>
<ListBoxItem>ListBox Item #2</ListBoxItem>
<ListBoxItem>ListBox Item #3</ListBoxItem>
</ListBox>
<!-- <Grid Grid.Row="1" Grid.RowSpan="2" Opacity="0.9" Background="WhiteSmoke"/> -->
<Canvas Name="WhiteMaskCanvas" Grid.Row="1" Grid.RowSpan="2" Background="White" Opacity="0.5"></Canvas>
</Grid>
</Window>
.
Class Part
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void SwitchOpacity_OnClick(object sender, RoutedEventArgs e)
{
int opacityVal = 0;
Task.Factory.StartNew(() =>
{
for (int i = 0; i <= 1000; i++)
{
int j = 0;
Thread.Sleep(100);
//Use ++ % to change Opacity
this.Dispatcher.Invoke(
DispatcherPriority.SystemIdle,
new Action(() =>
{
WhiteMaskCanvas.Opacity = ++opacityVal % 10 / 10.0;
}));
////Use Abs Cosine to Change Opacity
//this.Dispatcher.Invoke(
// DispatcherPriority.SystemIdle,
// new Action(() =>
// {
// WhiteMaskCanvas.Opacity =
// Math.Abs(Math.Sin(++opacityVal*0.1)) ;
// }));
}
});
}
}
.
The Result:
.
further code,
if want to make the canvas mask whole window, you can change the canvas to
<Canvas Name="WhiteMaskCanvas" Grid.Row="0" Grid.RowSpan="3" Background="White" Opacity="0.5"></Canvas>
and add code to class:
public MainWindow()
{
InitializeComponent();
WhiteMaskCanvas.Visibility = Visibility.Collapsed;
}
private void SwitchOpacity_OnClick(object sender, RoutedEventArgs e)
{
WhiteMaskCanvas.Visibility = Visibility.Visible;
int opacityVal = 0;
Task.Factory.StartNew(() =>
{
//below same as code above

Overlay Transparency should override Parent Background

I have a Overlay over my WPF Applicaiton, it shows some boarders as "context sensitive help". The boarders should now overrule the parent background and show the content behind (some kind of a view Port through the background).
The Controls look like this without Overlay:
With the Overlay Activated it looks like this:
The Overlay is a Usercontrol containing a ListBox of Items it should supply a boarder to.
The ListBoxPanel is a Canvas and the ListBoxItems are the Boarders(Buttons) you can see, which are moved over the UIElements they should surround using a ItemContainerStyle.
The Overlay looks like this:
<ItemsControl ItemsSource="{Binding HelpItems}" KeyboardNavigation.TabNavigation="Cycle" IsTabStop="True"
helpers:FocusHelper.FocusOnLoad="True" FocusVisualStyle="{StaticResource EmptyFocusVisual}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Button Command="{Binding ShowPopupCommand}" Background="Transparent" BorderThickness="2">
<Button.Style>
<Style>
<Setter Property="Button.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Left" Value="{Binding Left}" />
<Setter Property="Canvas.Top" Value="{Binding Top}" />
<Setter Property="FrameworkElement.Width" Value="{Binding Width}" />
<Setter Property="FrameworkElement.Height" Value="{Binding Height}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
I want the overlay to be transparent inside the boarder, while keeping the semitransparent dimming background on the list box, in other words the empty space of my ListBox should be Gray.
Is there any easy way I can get the Light Blue border to show the Content behind the panel without the semi transparent background of my Overlay?
This is the target result:
I did as well try to create a Opacity filter but it is the wrong way around. And it does not seem there is a easy way to invert a opacity filter.
Console,
Ok we have "to make some holes in the ice".
So here is a custom control : OverlayWithGaps that draws itself, with a given background that can be semi transparent.
OverlayWithGaps has a Rect Collection that represents the gaps :
public ObservableCollection<Rect> Gaps
{
get { return (ObservableCollection<Rect>)GetValue(GapsProperty); }
set { SetValue(GapsProperty, value); }
}
private static FrameworkPropertyMetadata fpm = new FrameworkPropertyMetadata(
null,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
null,
null
);
public static readonly DependencyProperty GapsProperty =
DependencyProperty.Register("Gaps", typeof(ObservableCollection<Rect>), typeof(OverlayWithGaps), fpm);
With AffectsRender, if that dependency property changes redrawing will happen.
Here is the drawing function :
protected override void OnRender(System.Windows.Media.DrawingContext dc)
{
if (Gaps != null && Gaps.Count > 0)
{
Geometry newGeometry = new RectangleGeometry(new Rect(0, 0, ActualWidth, ActualHeight));
foreach (var gap in Gaps)
// remove each rectangle of the global clipping rectangle :
// we make "a hole in the ice"
newGeometry = Geometry.Combine(newGeometry,
new RectangleGeometry(gap),
GeometryCombineMode.Exclude,
transform: null);
// When the geometry is finished, we make the hole
dc.PushClip(newGeometry);
}
dc.DrawRectangle(Background, null, new Rect(0, 0, ActualWidth, ActualHeight));
}
EDIT
3. Rectangles are provided from the ItemsControl ListViewItems
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
// overlay is the OverlayWithGaps instance
// in the window
overlay.Gaps = new ObservableCollection<Rect>(
itemsControl1.FindAllVisualDescendants()
.OfType<Grid>()
.Select(grid => {
Point relativePoint = grid.TransformToAncestor(this)
.Transform(new Point(0, 0));
return new Rect(relativePoint.X,
relativePoint.Y,
grid.ActualWidth,
grid.ActualHeight
);
})
);
}
Note that I select Grids in the LINQ query, because they are in the DataTemplate.
But the Linq query could select nearly anything (by name, ...)
The FindAllVisualDescendants() extension function can be found here :
Datagrid templatecolumn update source trigger explicit only updates first row
Here is the full working solution : http://1drv.ms/1OO2gWk
Best coding

How to bind data to a ListBox in a ControlTemplate?

What I am trying to do is to create some sort of "rooms"(like a chat group, a sharing center or whatever you want). All the room are created the same way, but each one of them contains different informations. Each of these rooms is contained in a TabItem. I managed to create dynamically all the Tabitems, to give those a Grid and a Canvas. But at the moment I am facing a problem: I created a ControlTemplate Called RoomMenu that will show different buttons and, the most important, the people connected in this room in a ListBox(I retrieve those people from a WebService each time I change the selected Tabitem). But since my ListBox is in a ControlTemplate I have no idea how to access the ListBox ItemSource to bind a generic List to it. Down Below is the code used to create my rooms and their content.
Here is my room menu class:
public class RoomMenu : ContentControl
{
public RoomMenu()
{
DefaultStyleKey = typeof(RoomMenu);
}
public string Current_room_id;
public string FullName;
public string Rights;
}
And here is the ControlTemplate located in generic.xaml:
<Style TargetType="test:RoomMenu">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="test:RoomMenu">
<Grid x:Name="MenuGrid">
<Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch" BorderBrush="Black" CornerRadius="2" Background="Black">
<StackPanel Orientation="Vertical">
<Border x:Name="Room_friend_border" Background="Gray" CornerRadius="4" Margin="5">
<ListBox x:Name="current_room_friends" ItemsSource="{Binding ''}" Margin="5" Height="230">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FullName}" Height="20"/>
<TextBlock Text="{Binding Rights}" Height="20"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Border>
<Border x:Name="Room_menu" Background="Gray" CornerRadius="4" Margin="5">
<StackPanel Orientation="Vertical" Margin="10">
<Button Content="Add item" Margin="0,2,0,2"/>
<Button Content="Set changes" Margin="0,2,0,2"/>
<Button Content="Invite friend" Margin="0,2,0,2"/>
<Button Content="Rename room" Margin="0,2,0,2"/>
<Button Content="Delete room" Margin="0,2,0,2"/>
</StackPanel>
</Border>
</StackPanel>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Here is my Dictionnary Class that contains the RoomMenu:
public class Rooms : TabItem
{
public string Room_guid;
public string Room_name;
public string Primary_user_guid;
public string Room_version;
public Grid Room_grid;
public Canvas Room_canvas;
public RoomMenu Room_menu;
}
And this is when I call my ControlTemplate and Add it to my TabItem's Grid:
public void Set_rooms_interface()
{
foreach (KeyValuePair<string, Rooms> kvp in rooms_list)
{
rooms_list[kvp.Key].Room_menu = new RoomMenu();
rooms_list[kvp.Key].Room_canvas = new Canvas();
rooms_list[kvp.Key].Room_grid = new Grid();
//instance grid columns
rooms_list[kvp.Key].Room_grid.ColumnDefinitions.Add(new ColumnDefinition() {Width = new GridLength(900)});
rooms_list[kvp.Key].Room_grid.ColumnDefinitions.Add(new ColumnDefinition());
//Refreshing room canvas
rooms_list[kvp.Key].Room_canvas.Height = rooms_list[kvp.Key].Room_grid.ActualHeight;
rooms_list[kvp.Key].Room_canvas.Width = rooms_list[kvp.Key].Room_grid.ActualWidth;
rooms_list[kvp.Key].Room_canvas = refresh_canvas(kvp.Key);
Grid.SetColumn(rooms_list[kvp.Key].Room_canvas, 0);
Grid.SetColumn(rooms_list[kvp.Key].Room_menu, 1);
//Add Canvas to Grid
rooms_list[kvp.Key].Room_grid.Children.Add(rooms_list[kvp.Key].Room_canvas);
rooms_list[kvp.Key].Room_grid.Children.Add(rooms_list[kvp.Key].Room_menu);
//Setting TabItem Name
rooms_list[kvp.Key].Header = rooms_list[kvp.Key].Room_name;
//Adding Grid to TabItem.Content
rooms_list[kvp.Key].Content = rooms_list[kvp.Key].Room_grid;
//Adding TabItem to TabControl
Room_tab.Items.Add(kvp.Value);
}
}
I'm sorry if the whole question is a bit long but it was the only way to explain clearly what I was trying to do. So if anyone could give me a hint or answer to do some databinding in a ControlTemplate it would greatly help me.
Thank You.
I think you started in the wrong direction when instantiating UI elements in code. The code behind should only contain one line assigning the people list to the current_room_friends DataContext.
Start with simpler examples of binding data to a ListBox like the beautiful planet example of Bea Stollnitz.

Categories

Resources