"I have two or more dockingManager, and I want every FloatingWindows to be dockable on every dockingManager."
floatingWindows must be created within a dockingManager, but it must be possible to dock it into another separate docking manager.
so when I do drag inside the first dockingManager the default positions are displayed. (4 icons: top, left, bottom, right)
but when I drag the floatingWindows into the second dockingManager nothing appears.
<Grid>
<avalonDock:DockingManager x:Name="dock1" Width="300" Height="200">
<avalonDockLayout:LayoutRoot>
<avalonDockLayout:LayoutRoot.FloatingWindows>
<avalonDockLayout:LayoutAnchorableFloatingWindow>
<avalonDockLayout:LayoutAnchorablePaneGroup DockHeight="100" DockWidth="100">
<avalonDockLayout:LayoutAnchorablePane x:Name="_LayoutAnchorablePane" FloatingHeight="150" FloatingWidth="150">
<avalonDockLayout:LayoutAnchorableTitle="FloatingWindow">
<Grid Background="CornflowerBlue">
</Grid>
</avalonDockLayout:LayoutAnchorable>
</avalonDockLayout:LayoutAnchorablePane>
</avalonDockLayout:LayoutAnchorablePaneGroup>
</avalonDockLayout:LayoutAnchorableFloatingWindow>
</avalonDockLayout:LayoutRoot.FloatingWindows>
</avalonDockLayout:LayoutRoot>
</avalonDock:DockingManager>
<avalonDock:DockingManager x:Name="dock2" Width="300" Height="200" >
<avalonDockLayout:LayoutRoot>
</avalonDockLayout:LayoutRoot>
</avalonDock:DockingManager/>
I also tried to force it from code, but it does not work!
LayoutAnchorable mAnchorableChilder=null;
public MainWindow()
{
InitializeComponent();
mAnchorableChilder = new LayoutAnchorable();
mAnchorableChilder.Title = "Sample dynamic avalondock";
_LayoutAnchorablePane.Children.Add(mAnchorableChilder);
Grid grid = new Grid { Background = new SolidColorBrush(Colors.Green) };
mAnchorableChilder.Content = grid;
}
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
I want to add canvas elements by user input. Something like when a button is clicked, a new <Ellipse/> element is added to the XAML file, inside the Canvas.
<Canvas x:Name="GraphDisplayFrame" Grid.Column="1" Grid.Row="0" Grid.ColumnSpan="3" Grid.RowSpan="4">
<Ellipse
Width="50"
Height="50"
Stroke="Black"
StrokeThickness="2"
Canvas.Left="100"
Canvas.Top="100" />
</Canvas>
I'm new to WPF, i'm not sure if this is the right way to do this.
The other thing i'm trying is System.Windows.Media but manipulating the XAMl file looks easier and nicer, since then the locations of the drawings are anchored to the canvas. I'm not sure if i can achieve something similar with System.Windows.Media.
So my question is in the title, but I'm open to other suggestions.
You probably want to learn about Bindings in WPF. Let's say you want your Ellipses be added by user's input (e.g. on Button click) to your Canvas. I'm not sure about Canvas usage for that purpose (it hasn't auto-alignments for child elements), so I used WrapPanel instead (to allow it align items). And we need 2 Buttons (to Add and Remove Ellipses). And I add a Label to display current amount of Ellipses that we have.
XAML:
<Window x:Class="WpfApp2.MainWindow"
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:local="clr-namespace:WpfApp2"
mc:Ignorable="d"
Name ="mainWindow"
Title="Main Window"
Width="800"
MaxWidth="800"
Height="450"
MaxHeight="450">
<Grid x:Name="MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50*"/>
<ColumnDefinition Width="50*"/>
<ColumnDefinition Width="50*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50*"/>
<RowDefinition Height="50*"/>
<RowDefinition Height="50*"/>
<RowDefinition Height="50*"/>
</Grid.RowDefinitions>
<Label Content="{Binding ElementName=mainWindow, Path=EllipsesCount, UpdateSourceTrigger=PropertyChanged}"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Grid.Row="0"
Background="DimGray"
Foreground="White"
Margin="15,35" />
<Button x:Name="BtnAddEllipse"
Content="ADD ELLIPSE"
Grid.Row="1"
Margin="10, 25" FontSize="22" FontWeight="Bold"
Background="LightGreen"/>
<Button x:Name="BtnRemoveEllipse"
Content="REMOVE ELLIPSE"
Grid.Row="2"
Margin="10, 25" FontSize="22" FontWeight="Bold"
Background="IndianRed"/>
<WrapPanel Orientation="Horizontal"
Background="Gainsboro"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Grid.Column="1"
Grid.Row="0"
Grid.ColumnSpan="3"
Grid.RowSpan="4" >
<ItemsControl ItemsSource="{Binding ElementName=mainWindow, Path=Ellipses, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</WrapPanel>
</Grid>
</Window>
Here you see that Label.Content property is binded to some EllipsesCount property (you'll see it in code-behind below). Also as WrapPanel is binded to Ellipses property.
Code-behind: (for copypaste purpose)
using System;
using System.Linq;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
namespace WpfApp2
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
// Text for Label about Ellipses amount in collection
private object _ellipsesCount = "Current ellipses count: 0";
public object EllipsesCount
{
get => _ellipsesCount;
set
{
_ellipsesCount = "Current ellipses count: " + value;
// When we set new value to this property -
// we call OnPropertyChanged notifier, so Label
// would be "informed" about this change and will get new value
OnPropertyChanged(nameof(EllipsesCount));
}
}
// Collection for Ellipses
private ObservableCollection<Ellipse> _ellipses;
public ObservableCollection<Ellipse> Ellipses
{
get => _ellipses;
set
{
_ellipses = value;
OnPropertyChanged(nameof(Ellipses));
}
}
// Hanlder, which would notify our Controls about property changes, so they will "update" itself with new values
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string propertyName = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
// Just for random colors
private readonly Random random = new Random();
public MainWindow()
{
InitializeComponent();
// Initialize collection of Ellipses
Ellipses = new ObservableCollection<Ellipse>();
// Handle when collection is changed to update Label
// with a new amount of Ellipses
Ellipses.CollectionChanged += delegate
{
// Update counter of ellipses when new one added or existing removed
EllipsesCount = Ellipses.Count;
};
BtnAddEllipse.Click += delegate
{
// Create an Ellipse with random stroke color
var ellipse = new Ellipse
{
Width = 50,
Height = 50,
Margin = new Thickness(3),
Stroke = new SolidColorBrush(Color.FromRgb((byte)random.Next(255), (byte)random.Next(255), (byte)random.Next(255))),
StrokeThickness = 3
};
// Add to collection of ellipses
Ellipses.Add(ellipse);
};
BtnRemoveEllipse.Click += delegate
{
// Check, that Ellipses collection isn't null and empty,
// so we can remove something from it
if (Ellipses?.Count > 0)
Ellipses.Remove(Ellipses.Last()); // Removing last element
};
}
}
}
So at result you see, actually, "content of collection of Ellipses", without adding Ellipses directly to window. Binding makes WrapPanel to use collection of Ellipses as source of child elements, that should be in that WrapPanel (instead of original my answer, where we add Ellipse to Canvas as Children).
ORIGINAL answer.
Yes, you can. For example (based on your XAML):
XAML (empty window):
<Window x:Class="WPFApp.MainWindow"
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:local="clr-namespace:WPFApp"
mc:Ignorable="d">
<!-- No even Grid here -->
</Window>
Code-behind (check comments also):
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Setting Window properties (they not exists in XAML)
// XAML: <Window ... Title="Main Window" Height="450" Width="800">...
this.Title = "Main Window";
this.Height = 450;
this.Width = 800;
// Create main Grid and register some its name
// XAML: ...
var mainGrid = new System.Windows.Controls.Grid();
this.RegisterName("MainGrid", mainGrid);
// Add row and column definitions (as Canvas below needs, at least 4 rows and 3 columns)
for (int i = 0; i < 4; i++)
{
mainGrid.RowDefinitions.Add(new System.Windows.Controls.RowDefinition { Height = new GridLength(50, GridUnitType.Star) });
if (i < 3) // Needn't 4th column
mainGrid.ColumnDefinitions.Add(new System.Windows.Controls.ColumnDefinition { Width = new GridLength(50, GridUnitType.Star) });
}
// Create Canvas and register its name too
// XAML: ...
var canvas = new System.Windows.Controls.Canvas
{
// Just to be able see it at Window
Background = System.Windows.Media.Brushes.LightGray
};
this.RegisterName("GraphDisplayFrame", canvas);
canvas.SetValue(System.Windows.Controls.Grid.ColumnProperty, 1);
canvas.SetValue(System.Windows.Controls.Grid.RowProperty, 0);
canvas.SetValue(System.Windows.Controls.Grid.ColumnSpanProperty, 3);
canvas.SetValue(System.Windows.Controls.Grid.RowSpanProperty, 4);
// Create Ellipse (child canvas element)
// XAML: ...
var ellipse = new System.Windows.Shapes.Ellipse
{
Width = 50,
Height = 50,
Stroke = System.Windows.Media.Brushes.Black,
StrokeThickness = 2
};
ellipse.SetValue(System.Windows.Controls.Canvas.LeftProperty, 100D);
ellipse.SetValue(System.Windows.Controls.Canvas.TopProperty, 100D);
// Add child Ellipse to Canvas
canvas.Children.Add(ellipse);
// or you already can find Canvas by its name:
(this.FindName("GraphDisplayFrame") as System.Windows.Controls.Canvas).Children.Add(ellipse);
// Add Canvas to MainGrid. Find Grid by its registered name too
(this.FindName("MainGrid") as System.Windows.Controls.Grid).Children.Add(canvas);
// Set main Grid as window content
this.Content = mainGrid;
}
}
So, as you can see, XAML markuping is quite more compact, that code-behinded one.
How to achieve an automatic full screen that not hides the taskbar, with no resize and no window style?
I tried to use the following code, but it doesn't work right, as shown in the image below.
XAML:
<Window x:Class="WPF_Test_Environment.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowState="Maximized" ResizeMode="NoResize" WindowStyle="None">
<DockPanel>
<Button DockPanel.Dock="Top" Height="50">Top</Button>
<Button DockPanel.Dock="Bottom" Height="50">Bottom</Button>
<Button DockPanel.Dock="Left" Width="50">Left</Button>
<Button DockPanel.Dock="Right" Width="50">Right</Button>
<Button Width="50" Height="50">Center</Button>
</DockPanel>
</Window>
Code-Behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight;
MinHeight = SystemParameters.MaximizedPrimaryScreenHeight;
MaxWidth = SystemParameters.MaximizedPrimaryScreenWidth;
MinWidth = SystemParameters.MaximizedPrimaryScreenWidth;
}
}
Here is the result:
As you can see, the "Bottom" button is partially underneath the taskbar, and I want it to be entirely above it. So, ideally, it would look as shown in the following image, but without the border on the top:
It can be done with calls to unmanaged code. Check this article to see how to do it. Basically, just remove your width and height settings from code-behind, implement the WindowSizing class from the article and call it from SourceInitialized event of the window.
Edit
The other solution would be to add reference to Windows Forms and use:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// Set the width and height values to the values of working area
this.Width = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Width;
this.Height = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height;
// Move the window to top left corner of the screen
this.Left = 0;
this.Top = 0;
}
Just make sure to remove WindowState="Maximized" from your window.
Not sure if any of these is elegant though.
First, let me state my intentions. This is the final result I am looking for.
Mockup Of Intent http://s18.postimg.org/x818zbfbb/image.png
The output of my code, however, fails to achieve this. Here's what I did. This is my MainWindow XAML.
<Window x:Class="App.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="" Height="200" Width="400"
WindowStartupLocation="CenterScreen" Name="ViewData">
<Grid Name="splMain" Background="{StaticResource GreyGradient}"></Grid>
</Window>
And this is the C# code for the dynamic RowDefitions creation:
private void ViewImgData(SubPod subPod)
{
var wb = new WebBrowser();
wb.Navigate(subPod.Image.Src);
var rowDefinition = new RowDefinition();
rowDefinition.Height = GridLength.Auto;
splMain.RowDefinitions.Add(rowDefinition);
Grid.SetRow(wb, 0);
((MainWindow)System.Windows.Application.Current.MainWindow).splMain.Children.Add(wb);
}
This I am calling from over here. It is guaranteed that this foreach loop would run more than once. However, my output window shows only 1 image instead of 2 or more, that too not taking up the whole space of the Window.
foreach (SubPod subPod in pod.SubPods)
{
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() => ViewImgData(subPod)));
}
Where have I mistaken? Thanks.
You add new rows, but place the new webbrowser component in the 0th row.
Try
Grid.SetRow(wb, splMain.RowDefinitions.Count-1);
instead, since you need to place new content in the new row.
EDIT:
To fit the grid height and width try adding this to your splMain grid
Width="{Binding ActualWidth,RelativeSource={RelativeSource AncestorType={x:Type Window}}" Height="{Binding ActualHeight,RelativeSource={RelativeSource AncestorType={x:Type Window}}"
see also Stretch Grid to window size
In my main page I try to show a list of stuff, and on this stuff a userControl as an overlay. In fact I never see it. (In the design view, my userControl is oaky)
XAML MainPage
<Grid>
<Grid x:name="MyPage">
<!-- All this part is visible -->
//Button
//Button
//nice Pic
//Button
</Grid>
<cat:CatPagecontrol x:Name="CatTool" Visibility="Visible" HorizontalAlignment="Center" VerticalAlignment="Center">
<cat:CatPagecontrol.Transitions>
<TransitionCollection>
<PopupThemeTransition/>
</TransitionCollection>
</cat:CatPagecontrol.Transitions>
</cat:CatPagecontrol>
<!-- EDIT I remove the Grid "CatGrid" And the ZIndex -->
</Grid>
I try to switch the ZIndex, no results.
C# File
public MainView()
{
this.CatTool = new CatPagecontrol();
//this.CatTool.Visibility = Visibility.Collapsed;
}
private void showCatSelector()
{
this.CatTool.Visibility = Visibility.Visible;
}
After that I need that one of my buttons show the overlay when clicked.
If you know how to show it, I'm yours. Thanks.
edit : solution find.
Voila !
I've find my problem :
public CatPagecontrol()
{
this.InitializeComponent();
}
I just Initialized in the correct section.
I have UserControl which I display like this, it's for previewing a receipt ticket before printing:
<ScrollViewer x:Name="xzScroll" Template="{StaticResource scrollView}" Height="488" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch">
<Border x:Name="xzPreview" BorderThickness="0" Background="White" Margin="0,0,10,0" Padding="15">
// The UserControl
</Border>
</ScrollViewer>
When the user wants to print the receipt, I remove the UserControl from its parent Border, and try to re-measure and re-arrange the control according to the printeable area:
public void Print()
{
PrintDialog dlg = new PrintDialog();
this.Measure(new Size(dlg.PrintableAreaWidth, double.PositiveInfinity));
this.Arrange(new Rect(this.DesiredSize));
this.UpdateLayout();
dlg.PrintTicket.PageMediaSize = new PageMediaSize(this.ActualWidth, this.ActualHeight);
....
}
However, the Height and Width properties won't change, resulting in a faulty print with messed up margins and some text clipping on the sides.
When I create a new instance of my UserControl in code, and then use the Measure and Arrange methods, I see the Width and Height properties change according to the PrinteableAreaWidth, resulting in a proper receipt ticket.
How can I make sure the Width and Height properties are properly getting set?
Is it right that you want to to resize the Usercontrol?
If yes, why don't create a Class (ViewModel) for the Usercontrol with the two Properties Height and Width and bind the User Control to these Properties.
Than you can change the size without removing the Usercontrol.
Here for Example how such a ViewModel could look like. You will need to implement the INotifyPropertyChanged.
public class UserControlViewModel:INotifyPropertyChanged
{
private double _height;
private double _width;
public double _height
{
get { return _height;}
set {
if(_height == value)
return;
_height = value;
OnPropertyChanged();
}
public double _width
{
get { return _width;}
set {
if(_width == value)
return;
_width = value;
OnPropertyChanged();
}
And in Xaml you can bind it this way.
<ScrollViewer x:Name="xzScroll" Template="{StaticResource scrollView}" Height="488" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch">
<Border x:Name="xzPreview" BorderThickness="0" Background="White" Margin="0,0,10,0" Padding="15">
<MyUserControl
DataContext = "{Binding MyControlViewModelObject}"
Height = "{Binding Height}"
Width = "{Binding Width}"/>
</Border>
</ScrollViewer>
It is possible that you have declared the UI elements in your UserControl with exact Margin and/or Height and Width dimensions... of course, I can't be sure about that because you didn't show us your relevant code.
However, if this is the case, then you won't be able to rearrange them by re-sizing the UserControl externally. The solution is to use Grid controls to organise your UI elements, so that they can be automatically re-sized when the UserControl is resized. See the Grid Class page on MSDN for further information.