Wpf drag and drop application - c#

i am new to WPF and i am trying to develop drag and drop functionality in my application. I have two user controls Window1 and Window2. How do I enable drag and drop on any of this user controls by clicking only in the orange area. Only orange area of the user control should be drag and drop enabled. Gray area should not be drag and drop enabled. I mean if we want to drag user control then we have to click in the orange area and gray area will also be dragged with it. If we click on gray area then user control should not move. Please check the image below which will help in understanding the question.https://www.dropbox.com/sh/wj9mcbyi9wpcxgq/AAAb9r_aWxKm2Eah3PrT__5sa?dl=0Thanks in advance.

If you want to do it yourself then you can use my implementation here: https://stackoverflow.com/a/17014906/145757
Otherwise you can check the Blend SDK which includes the MouseDragElementBehavior.

Thanks a lot #Pragmateek for your help, it worked like a charm. Below is my code implemented. I've a user control UCDragme, it has a dedicated orange drag area TBDragme.
<UserControl x:Class="NSR3.UCDragme"
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="500" d:DesignWidth="300">
<Grid Background="Gray">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Background="Orange" x:Name="TBDragme" Text="Dragme" />
<TextBlock Grid.Column="0" Grid.Row="1" Grid.RowSpan="2" Background="AliceBlue" Margin="20" Text="No drag"></TextBlock>
</Grid>
</UserControl>
Main window Home:
<Window x:Class="NSR3.Home"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Home"
xmlns:nsr="clr-namespace:NSR3">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Canvas x:Name="panel">
</Canvas>
<Button Content="Add" Grid.Row="1" Grid.Column="0" Click="Button_Click" />
</Grid>
</Window>
drag-and-drop engine in the Home window code-behind:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace NSR3
{
/// <summary>
/// Interaction logic for Home.xaml
/// </summary>
public partial class Home : Window
{
UCDragme box;
public Home()
{
InitializeComponent();
box = new UCDragme();
TextBlock tb = (TextBlock)box.FindName("TBDragme");
tb.MouseLeftButtonDown += box_MouseLeftButtonDown;
tb.MouseLeftButtonUp += box_MouseLeftButtonUp;
tb.MouseMove += box_MouseMove;
panel.Children.Add(box);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
box = new UCDragme();
TextBlock tb=(TextBlock)box.FindName("TBDragme");
tb.MouseLeftButtonDown += box_MouseLeftButtonDown;
tb.MouseLeftButtonUp += box_MouseLeftButtonUp;
tb.MouseMove += box_MouseMove;
panel.Children.Add(box);
}
private TextBlock draggedBox;
private Point clickPosition;
private void box_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
draggedBox = sender as TextBlock;
clickPosition = e.GetPosition(draggedBox);
draggedBox.CaptureMouse();
}
private void box_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
draggedBox.ReleaseMouseCapture();
draggedBox = null;
//box = null;
}
private void box_MouseMove(object sender, MouseEventArgs e)
{
if (draggedBox != null)
{
Point currentPosition = e.GetPosition(panel);
box.RenderTransform = draggedBox.RenderTransform as TranslateTransform ?? new TranslateTransform();
TranslateTransform transform = box.RenderTransform as TranslateTransform;
transform.X = currentPosition.X - clickPosition.X - draggedBox.Margin.Left;
transform.Y = currentPosition.Y - clickPosition.Y - draggedBox.Margin.Right;
}
}
}
}

Related

How to close current user Control and open new User control in WPF inside user control

I am new in WPF application i have to develop app with user control, User control will work like pages
I have open user control in MainWindow which will select language upon click and then close (current) language selection control and open another
MainWindow Code
<Window x:Class="WorkForceVisitor.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:WorkForceVisitor"
mc:Ignorable="d"
Title="Work Force Pro Visitor" Icon="Images/favicon.ico" Height="800" Width="1200">
<Window.Background>
<ImageBrush ImageSource="Images/bg.png"/>
</Window.Background>
<Grid Margin="10,0,1,5" RenderTransformOrigin="0.556,0.496" Height="754" VerticalAlignment="Bottom">
<StackPanel Name="myStack" Grid.Row="1" >
</StackPanel>
</Grid>
</Window>
MainWindow.cs
private Header _Header;
private Visitor _Visitor;
private Control _currentUser;
public MainWindow()
{
InitializeComponent();
_Header = new Header();
_LanguageSelection = new LanguageSelection();
_Visitor = new Visitor();
_currentUser = _LanguageSelection;
myStack.Children.Add(_currentUser);
}
user will click either arabic or english
upon button click we will close LanguageSelection control
and open Visitor controll in StackPanel Name="myStack"
which is inside the mainWindow
LanguageSelection
<UserControl x:Class="WorkForceVisitor.LanguageSelection"
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:WorkForceVisitor"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid Margin="10,0,1,5" RenderTransformOrigin="0.556,0.496" Height="754" VerticalAlignment="Bottom">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0*"/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image MouseDown="EnglishPress" Grid.Column="1" HorizontalAlignment="Right" Height="200" Margin="0,0,38,272" VerticalAlignment="Bottom" Width="290" Source="Images/english.PNG">
<Image.OpacityMask>
<ImageBrush ImageSource="Images/arabic.PNG"/>
</Image.OpacityMask>
</Image>
<Image MouseDown="AranbicPress" Grid.Column="2" Height="200" Margin="50,0,0,272" VerticalAlignment="Bottom" Source="Images/arabic.PNG" RenderTransformOrigin="0.511,0.527" HorizontalAlignment="Left" Width="285">
<Image.OpacityMask>
<ImageBrush ImageSource="Images/english.PNG"/>
</Image.OpacityMask>
</Image>
<Image Grid.Column="1" HorizontalAlignment="Right" Height="100" Margin="0,0,440,517" VerticalAlignment="Bottom" Width="294" Grid.ColumnSpan="2" Source="Images/Logo.png"/>
</Grid>
</UserControl>
languageselection.cs
static bool isEnglish = false;
private void AranbicPress(object sender, MouseButtonEventArgs e)
{
// need to close current control and show visitor control in mainWindow
}
private void EnglishPress(object sender, MouseButtonEventArgs e)
{
// need to close current control and show visitor control in mainWindow
isEnglish = true;
}
I am not a pro, but this should work:
MainWindow.cs
public static Window Current;
private Header _Header;
private Visitor _Visitor;
private Control _currentUser;
public MainWindow()
{
Current = this;
InitializeComponent();
_Header = new Header();
_LanguageSelection = new LanguageSelection();
_Visitor = new Visitor();
_currentUser = _LanguageSelection;
myStack.Children.Add(_currentUser);
}
languageselection.cs
static bool isEnglish = false;
private void AranbicPress(object sender, MouseButtonEventArgs e)
{
MainWindow.Current.myStack.Children.Clear();
MainWindow.Current.myStack.Children.Add(MainWindow.Current._Visitor);
}
private void EnglishPress(object sender, MouseButtonEventArgs e)
{
MainWindow.Current.myStack.Children.Clear();
MainWindow.Current.myStack.Children.Add(MainWindow.Current._Visitor);
isEnglish = true;
}
However:
1) I don't think you need stackpanel inside of the grid for just one child;
2) I don't think you need to initialize your usercontrols before user needs them;
3) I would probably better create methods in the MainWindow to replace the controls.

Correct way of updating Property so that loading doesn't stop UI?

Sorry about the headline but it was the best I could come up with. Let me explain my problem: I have a WPF application that has a Menu looking much like your standard top menu that only takes up 5% of the screen. Click a menu item and the view below changes. The menu control is home-brewed because of reasons: Dynamic changes to menu-items, weird UI that doesn't fit existing controls, etc.
The menu changing view part is done using a ContentControl that binds to a "CurrentMenuView" property. When a menu item is clicked, this happens (pseudo-code):
private async void Button_Pressed(...)
{
await MakeSomeVisualMenuChanges();
CurrentMenuView = new CarsView();
await MakeSomOtherStuff();
}
The problem is that some views take some time to load, which makes the other steps happen slow also. I'd like to start loading the "CarsView" but at the same time (not after) continue with the other changes. So the user can see stuff happening.
I can solve this by using Task.Run() but that seems wrong as it puts stuff in a different context.
What is the correct / better way of dealing with this?
EDIT:
Thanks for all answers, as I expected this is not easy to explain. Let me try with a simple example:
MainWindows.xaml:
<Window x:Class="WpfApp32.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"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="300" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<Button Grid.Row="0" Width="50" Content="Click" Click="Button_Click" />
<ContentControl Grid.Row="1" Width="200" Height="200" Content="{Binding PageContent, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
<TextBlock Grid.Row="2" Text="Bottom" Width="300" x:Name="BottomText" />
</Grid>
</Window>
Code-Behind:
using System.Windows;
using System.ComponentModel;
namespace WpfApp32
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
BottomText.Text = "AndNowforSomethingCompletelyDifferent";
PageContent = new UserControl1();
}
private object pageContent;
public object PageContent
{
get => pageContent;
set
{
pageContent = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(PageContent)));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
UserControl1.xaml:
<UserControl x:Class="WpfApp32.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"
Loaded="UserControl_Loaded"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<TextBlock x:Name="CtrlTextBlock" Width="100"/>
</Grid>
</UserControl>
UserControl1.cs:
using System.Windows;
using System.Windows.Controls;
namespace WpfApp32
{
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
private void Init()
{
System.Threading.Thread.Sleep(2000);
CtrlTextBlock.Text = "Loaded";
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
Init();
}
}
}
So this is stripped from async etc and just showing the issue. When the button is pressed, the UserControl1 is loaded but it takes 2 seconds to load. Until then, the text in the "BottomText" element remains unset.
As I said before, I can solve this by doing something like this in the button click:
private void Button_Click(object sender, RoutedEventArgs e)
{
BottomText.Text = "AndNowforSomethingCompletelyDifferent";
System.Threading.Tasks.Task.Run(() => Application.Current.Dispatcher.Invoke(() => PageContent = new UserControl1()));
}
But not sure that is the way to go. So the basic issue here, is that a ContentControl is bound to a property and setting that property might take some time. While that is loading I don't want execution in the MainWindow to be halted (I want the BottomText element to display "AndNowforSomethingCompletelyDifferent" immediately).
Here's an example that simulates 3 seconds of loading... It's not an extremely complex UI and binding to complex DataTemplates, especially nested, can slow things a bit but normally the drag comes from pulling the data.
The trick is having a clever UI that keeps things moving but also lets the user know it's waiting on something else to continue. The infamous loading bar for example... Not that I would use that exact process but that's the right idea.
Note and disclaimer: I almost despise code behind unless it's in a custom control of some type; never in the view. I always prefer MVVM and using a ViewModel for binding; but not to build or control the UI only for the data the UI uses. All that said because this example is none of that. I simply made the controls on the view and put the code behind for answering this question, with example, as simple as possible.
The View
<Window x:Class="Question_Answer_WPF_App.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="500"
Width="800">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition />
</Grid.RowDefinitions>
<ToggleButton x:Name="menuButton"
Content="Menu"
Click="MenuButton_Click" />
<!--I do not recommend binding in the view like this... Make a custom control that does this properly.-->
<Grid x:Name="menu"
Visibility="{Binding IsChecked, Converter={StaticResource BooleanToVisibilityConverter}, ElementName=menuButton}"
VerticalAlignment="Top"
Grid.Row="1"
Background="Wheat">
<StackPanel x:Name="menuItems">
<TextBlock Text="simulated...." />
<TextBlock Text="simulated...." />
<TextBlock Text="simulated...." />
<TextBlock Text="simulated...." />
<TextBlock Text="simulated...." />
<TextBlock Text="simulated...." />
<TextBlock Text="simulated...." />
<TextBlock Text="simulated...." />
<TextBlock Text="simulated...." />
<TextBlock Text="simulated...." />
</StackPanel>
<StackPanel Name="menuLoading">
<TextBlock Text="Loading..."
FontSize="21" />
<ProgressBar IsIndeterminate="True"
Height="3" />
</StackPanel>
</Grid>
</Grid>
</Window>
Code Behind the View
using System.Threading.Tasks;
using System.Windows;
namespace Question_Answer_WPF_App
{
public partial class MainWindow : Window
{
public MainWindow() => InitializeComponent();
private Task SimulateLoadingResourcesAsnyc() => Task.Delay(3000);
private async void MenuButton_Click(object sender, RoutedEventArgs e)
{
menuItems.Visibility = Visibility.Collapsed;
menuLoading.Visibility = Visibility.Visible;
await SimulateLoadingResourcesAsnyc();
menuItems.Visibility = Visibility.Visible;
menuLoading.Visibility = Visibility.Collapsed;
}
}
}

Undesired button resizing after being transformed

I'm trying to create an expandable/collapsible menu for a personal project of mine. I have everything almost where I want it (in terms of it being behaving as expected anyway). When I collapse my menu, I want the buttons to rotate to a vertical position and not resize (Or at least resize to something that still fits the text). At the moment, the buttons rotate, then shrink vertically (what was/is the width) along with the parent control, which cuts off much of the contents. I can see why this would happen, but I can't think of a way around it that seems right to me.
Here is the behavior I'm seeing:
Before: After:
As you can see, the buttons are shrinking along their now-vertical width (to what I assume would be the width of the enclosing StackPanel).
Here is the code I am using:
ExpaningMenu.xaml
<UserControl x:Class="Budgety.Controls.ExpandingMenu"
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:Budgety.Controls"
mc:Ignorable="d"
Name="MainExpandingMenu"
MinWidth="32"
d:DesignHeight="300" d:DesignWidth="100">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Name="MenuPanel" Width="100" HorizontalAlignment="Left" Background="{DynamicResource BackColor}" Grid.Row="1">
<!--Contents will go here-->
</StackPanel>
<Button Name="StateToggle" Width="100" Height="32" FontSize="18" VerticalAlignment="Center" HorizontalAlignment="Stretch" Panel.ZIndex="1" Background="{DynamicResource BackColor}" BorderThickness="0" Click="Button_Click" Content="«"></Button>
</Grid>
</UserControl>
ExpandingMenu.xaml.cs
public partial class ExpandingMenu : UserControl
{
public ExpandingMenu()
{
InitializeComponent();
//For testing purposes.
MenuPanel.Children.Add(new ExpandingMenuButton("TEST ITEM 1"));
MenuPanel.Children.Add(new ExpandingMenuButton("TEST ITEM 2"));
MenuPanel.Children.Add(new ExpandingMenuButton("TEST ITEM 3"));
MenuPanel.Children.Add(new ExpandingMenuButton("TEST ITEM 4"));
MenuPanel.Children.Add(new ExpandingMenuButton("TEST ITEM 5xxx"));
foreach (UIElement element in MenuPanel.Children)
{
(element as ExpandingMenuButton).HorizontalAlignment = HorizontalAlignment.Left;
}
}
#region Events
private void Button_Click(object sender, RoutedEventArgs e)
{
if (MenuPanel.Width == 100) //Need to collapse
{
StateToggle.Width = MenuPanel.Width = 32;
(sender as Button).Content = "\u00BB";
//Flip all children of this control (so far, assuming only ExpandingMenuButtons)
foreach (UIElement element in MenuPanel.Children)
{
(element as ExpandingMenuButton).LayoutTransform = new RotateTransform(-90);
//This works to resize to 100 tall (not ideal...)
//(element as ExpandingMenuButton).Width = 100;
//This does not seem to size to auto, which SHOULD make each button as long as the text requires... (this behavior is far less than ideal...)
//(element as ExpandingMenuButton).Width = Double.NaN;
}
}
else //Need to expand
{
StateToggle.Width = MenuPanel.Width = 100;
(sender as Button).Content = "\u00AB";
//Flip all children of this control (so far, assuming only ExpandingMenuButtons)
foreach (UIElement element in MenuPanel.Children)
{
(element as ExpandingMenuButton).LayoutTransform = new RotateTransform(0);
}
}
}
#endregion
}
ExpandingMenuButton.xaml
<UserControl x:Class="Budgety.Controls.ExpandingMenuButton"
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:Budgety.Controls"
mc:Ignorable="d"
d:DesignHeight="30" d:DesignWidth="100"
Height="30"
Name="ButtonControl">
<Grid Name="ButtonGrid" Height="30">
<ToggleButton Name="MenuButton" Background="Aqua" BorderThickness="1" Content="TEST"></ToggleButton>
</Grid>
</UserControl>
ExpandingMenuButton.xaml.cs
public partial class ExpandingMenuButton : UserControl
{
//Will definitely want custom functionalty here. TBD. Nothing special so far.
#region Constructors
public ExpandingMenuButton()
{
InitializeComponent();
}
public ExpandingMenuButton(string sText)
{
InitializeComponent();
MenuButton.Content = sText;
}
#endregion
}
If you'd like to test the code out, it should work placed in a normal grid as I have (The above mentioned UserControls I've made are in a Controls folder within the project):
<Window
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:Budgety"
xmlns:Controls="clr-namespace:Budgety.Controls" x:Class="Budgety.MainTest"
mc:Ignorable="d"
Title="MainTest" Height="600" Width="800">
<Grid>
<Controls:ExpandingMenu x:Name="ExpandingMenu" HorizontalAlignment="Left"/>
</Grid>
</Window>
After all is said and done, here is the behavior/look I am after (notice buttons are not shortened)
The reason for the layout you're seeing is the fixed height constraint you placed in ExpandingMenuButton: Height="30" on both the UserControl and the Grid element. You can change it to MinHeight.
In addition, when you set the width of the MenuPanel, you're also containing the height of the buttons, because you apply a transform.
Here's one way to fix this:
private void Button_Click(object sender, RoutedEventArgs e)
{
if (StateToggle.IsChecked == true)
{
StateToggle.Content = "\u00BB";
foreach (FrameworkElement element in MenuPanel.Children)
element.LayoutTransform = new RotateTransform(-90);
}
else
{
StateToggle.Content = "\u00AB";
foreach (FrameworkElement element in MenuPanel.Children)
element.LayoutTransform = null;
}
}
XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Name="MenuPanel"
HorizontalAlignment="Left"
Background="{DynamicResource BackColor}"
Grid.Row="1">
<!--Contents will go here-->
</StackPanel>
<ToggleButton Name="StateToggle"
FontSize="18"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
Panel.ZIndex="1"
Background="{DynamicResource BackColor}"
BorderThickness="0"
Click="Button_Click"
Content="«" />
</Grid>
As a general rule, don't specify widths and heights in WPF - let the layout system do the measuring for you according to the content.

XAML Runtime Usercontrol Binding

I have been fixating on this from some time:
I am developing a windows phone app:
I have a XAML Page as a template and three UserControls:
One of which has map-layout, one generalInfo-layout, Summary+Pic layout.
I want to create 3 buttons at the top and change the active UserControl respectively.
I dont want to you use a PivotPage.
HELP? Advice? Code?
One very primitive approach would be to subscribe to the Click event of all 3 buttons and basically just change the Visibility property of your UserControls in the event handlers appropriately.
Of course there are other approaches you might want to consider - like using the MVVM pattern or using TabControl and TabItem from the sdk if available for WP7 or using event triggers - but this can be a good starting point.
Your MainPage should look something like this:
<UserControl x:Class="SilverlightApplication10.MainPage"
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:silverlightApplication10="clr-namespace:SilverlightApplication10"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel x:Name="LayoutRoot"
Orientation="Horizontal"
Background="White">
<Button Height="30"
Content="content1"
Click="Button_Click" />
<Button Height="30"
Content="content2"
Click="Button_Click_1" />
<Button Height="30"
Content="content3"
Click="Button_Click_2" />
</StackPanel>
<Grid Grid.Row="1">
<silverlightApplication10:SilverlightControl1 x:Name="ctrl1"
Visibility="Collapsed" />
<silverlightApplication10:SilverlightControl2 x:Name="ctrl2"
Visibility="Collapsed" />
<silverlightApplication10:SilverlightControl3 x:Name="ctrl3"
Visibility="Collapsed" />
</Grid>
</Grid>
</UserControl>
And then your event handlers should take care of setting the Visibility property of all these UserControls:
private void Button_Click(object sender, RoutedEventArgs e)
{
ctrl1.Visibility = Visibility.Visible;
ctrl2.Visibility = Visibility.Collapsed;
ctrl3.Visibility = Visibility.Collapsed;
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
ctrl2.Visibility = Visibility.Visible;
ctrl1.Visibility = Visibility.Collapsed;
ctrl3.Visibility = Visibility.Collapsed;
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
ctrl3.Visibility = Visibility.Visible;
ctrl1.Visibility = Visibility.Collapsed;
ctrl2.Visibility = Visibility.Collapsed;
}

Add Usercontrol To A Canvas

I have seen may examples one of them been
Add WPF control at runtime
Seem this solution has work for a lot of people. What the hell am I doing wrong? My Label won't Show on the canvas.
Label l = new Label();
l.Background = new LinearGradientBrush(Colors.Black, Colors.Black, 0);
canBackArea.Children.Add(l);
l.Visibility = System.Windows.Visibility.Visible;
l.Content = "Hello";
Canvas.SetLeft(l,20);
Canvas.SetTop(l, 20);
Canvas.SetZIndex(l, lableList.Count);
Canvas Has a white color, Thus the Background.
canBackArea is a Canvas
XML CODE
<ScrollViewer Grid.Row="2" HorizontalScrollBarVisibility="Visible">
<Canvas Name="canBackArea"
Width="500"
Height="300"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Background="White"
MouseMove="canBackArea_MouseMove">
<telerik:RadContextMenu.ContextMenu>
<telerik:RadContextMenu Name="mnuBack"
ItemClick="ContextMenu_ItemClick"
Opened="mnuBack_Opened">
<telerik:RadMenuItem Name="mBackground" Header="Set Background Image" />
<telerik:RadMenuItem Name="mSize" Header="Set Size" />
<telerik:RadMenuItem Name="mLable" Header="Add Text" />
<telerik:RadMenuItem Name="mChangeText" Header="Change Text" />
</telerik:RadContextMenu>
</telerik:RadContextMenu.ContextMenu>
<Image Name="imgBackground" />
</Canvas>
</ScrollViewer>
After Add a lot of labels.
This is my MainWindow.xaml
<Window x:Class="WpfApplication1.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">
<Canvas x:Name="canBackArea">
</Canvas>
and this is my codebehind.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Label l = new Label();
canBackArea.Children.Add(l);
l.Visibility = System.Windows.Visibility.Visible;
l.Content = "Hello";
Canvas.SetLeft(l, 20);
Canvas.SetTop(l, 20);
}
This works perfectly fine.
http://i.imgur.com/JooqS.png
It could depend on the context your using it in?
I have tried to reproduce your issue and I suspect the possible issues should be that
No Foreground color is set to Label controls.
zIndex should be more than any other children controls I think as Canvas.SetZIndex(l, canBackArea.Children.Count);
Below is what I have tried and tested.
XAML Code
<Window x:Class="TestApplication.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" Loaded="Window_Loaded">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="269*" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Label Content="New Label Content" Height="30" />
<TextBox x:Name="txtLabelContent" Width="200" Height="30"></TextBox>
<Button Margin="10 0 0 0" Height="30" Width="70" Click="Button_Click">Add Label</Button>
</StackPanel>
<Canvas Grid.Row="1" x:Name="canBackArea" Background="White" Grid.RowSpan="2">
</Canvas>
</Grid>
</Window>
Window code-behind
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace TestApplication
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Label l = new Label();
l.Background = new LinearGradientBrush(Colors.Black, Colors.Black, 0);
l.Foreground = new LinearGradientBrush(Colors.White, Colors.White, 0);
canBackArea.Children.Add(l);
l.Visibility = System.Windows.Visibility.Visible;
l.Content = txtLabelContent.Text;
Canvas.SetLeft(l, 20);
Canvas.SetTop(l, 20);
Canvas.SetZIndex(l, canBackArea.Children.Count);
}
}
}
using your xaml and this
private void mnuBack_ItemClick(object sender, Telerik.Windows.RadRoutedEventArgs e)
{
Label l = new Label();
canBackArea.Children.Add(l);
l.Visibility = System.Windows.Visibility.Visible;
l.Content = "Hello";
Canvas.SetLeft(l, 20);
Canvas.SetTop(l, 20);
Canvas.SetZIndex(l, lableList.Count);
lableList.Add(l);
}
I can add labels
The Problem was i was using styles and it is some how over writing my lable, i replaced it with textbox and every thing seems fine....

Categories