I have a created a box like this and now i'm trying to drag and drop the box, with rectangles and other objects I did it, but with this I don't know how to do.
Here is the code of how I did the box
XAML:
<Canvas>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox Text="{Binding Header,UpdateSourceTrigger=PropertyChanged}"
BorderBrush="Black" BorderThickness="1" Canvas.Left="41" Canvas.Top="10" Width="97" />
<TextBox Text="{Binding Text,UpdateSourceTrigger=PropertyChanged}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto"
AcceptsReturn="True"
BorderBrush="Black" BorderThickness="1" Grid.Row="1" Canvas.Left="41" Canvas.Top="39" Height="53" Width="97" />
</Grid>
</Canvas>
The c# code:
public partial class MyBox : UserControl
{
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register("Header", typeof(string), typeof(MyBox),null);
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Content", typeof(string), typeof(MyBox),null);
public string Header
{
get { return GetValue(HeaderProperty) as string; }
set { SetValue(HeaderProperty, value); }
}
public string Text
{
get { return GetValue(TextProperty) as string; }
set { SetValue(TextProperty, value); }
}
public MyBox()
{
InitializeComponent();
this.DataContext = this;
}
And this is the code for adding another box:
private void Button_Click(object sender, RoutedEventArgs e)
{
panel.Children.Add(new MyBox
{
//LayoutRoot.Children.Add(new MyBox {
Header = "Another box",
Text = "...",
// BorderBrush = Brushes.Black,
BorderThickness = new Thickness(1),
Margin = new Thickness(10)
});
}
Here is a sample, inspired from https://stackoverflow.com/a/1495486/145757 (thanks Corey), slightly adapted, simplified (no additional boolean) and enhanced (take margins into account) for our use-case:
First I've modified the box so that it has a dedicated drag area:
<UserControl x:Class="WpfApplication1.MyBox"
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="300" d:DesignWidth="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="Drag me" />
<TextBox Text="{Binding Header,UpdateSourceTrigger=PropertyChanged}"
BorderBrush="Black" BorderThickness="1" Margin="2" Grid.Row="1" />
<TextBox Text="{Binding Text,UpdateSourceTrigger=PropertyChanged}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto"
AcceptsReturn="True"
BorderBrush="Black" BorderThickness="1" Margin="2" Grid.Row="2" />
</Grid>
</UserControl>
MainWindow XAML slightly modified:
<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"
xmlns:local="clr-namespace:WpfApplication1">
<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>
And the drag-and-drop engine is in the code-behind:
using System.Windows;
using System.Windows.Media;
using System.Windows.Input;
using System.Windows.Controls;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MyBox box = new MyBox
{
Header = "Another box",
Text = "...",
BorderBrush = Brushes.Black,
BorderThickness = new Thickness(1),
Margin = new Thickness(10)
};
box.MouseLeftButtonDown += Box_MouseLeftButtonDown;
box.MouseLeftButtonUp += Box_MouseLeftButtonUp;
box.MouseMove += Box_MouseMove;
panel.Children.Add(box);
}
private MyBox draggedBox;
private Point clickPosition;
private void Box_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
draggedBox = sender as MyBox;
clickPosition = e.GetPosition(draggedBox);
draggedBox.CaptureMouse();
}
private void Box_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
draggedBox.ReleaseMouseCapture();
draggedBox = null;
}
private void Box_MouseMove(object sender, MouseEventArgs e)
{
if (draggedBox != null)
{
Point currentPosition = e.GetPosition(panel);
draggedBox.RenderTransform = draggedBox.RenderTransform ?? new TranslateTransform();
TranslateTransform transform = draggedBox.RenderTransform as TranslateTransform;
transform.X = currentPosition.X - clickPosition.X - draggedBox.Margin.Left;
transform.Y = currentPosition.Y - clickPosition.Y - draggedBox.Margin.Right;
}
}
}
}
have a look at Blend Interaction behaviours. I did a sample a while back http://invokeit.wordpress.com/2012/02/10/wp7-drag-drop-example/
Related
I have some buttons in a toolbar. One of the buttons opens a popup. It works fine when the button is clicked while the button is shown regularly. When the button is clicked while it is in the toolbars overflow area the popup does not work. It is shown and immediately closed. Is there a solution for this?
XAML
<Window x:Class="WpfApp5.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="100" Width="100"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<DockPanel LastChildFill="True">
<ToolBar DockPanel.Dock="Top">
<Button Content="First"></Button>
<Button Content="Second"></Button>
<Button Content="Third"></Button>
<Button Content="Popup" Click="OnClick"></Button>
<Popup IsOpen="{Binding IsPopupOpen, Mode=TwoWay}" StaysOpen="False">
<Border BorderBrush="Black" BorderThickness="2">
<Grid Width="150" Height="150" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Text="Popup"></TextBlock>
<Button Grid.Row="1" Content="Button In Popup" Click="PopupButtonOnClick"></Button>
</Grid>
</Border>
</Popup>
</ToolBar>
<Grid Background="White"></Grid>
</DockPanel>
</Window>
Code behind
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
namespace WpfApp5
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
private bool _isPopupOpen;
public MainWindow()
{
InitializeComponent();
}
public bool IsPopupOpen
{
get => _isPopupOpen;
set
{
if (value == _isPopupOpen) return;
_isPopupOpen = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private void OnClick(object sender, RoutedEventArgs e)
{
IsPopupOpen = true;
}
private void PopupButtonOnClick(object sender, RoutedEventArgs e)
{
MessageBox.Show("I did it");
}
}
}
I have the following glass effect which was adapted from WPF-MediaKit, the code for this is
public class GlassBehavior : Behavior<FrameworkElement>
{
private FrameworkElement attachedObject;
private readonly VisualBrush directVisualBrush = new VisualBrush();
private readonly Rectangle surrogateVisual = new Rectangle();
private readonly VisualBrush surrogateVisualBrush = new VisualBrush();
public GlassBehavior()
{
RenderOptions.SetEdgeMode(directVisualBrush, EdgeMode.Aliased);
RenderOptions.SetCachingHint(directVisualBrush, CachingHint.Cache);
RenderOptions.SetEdgeMode(surrogateVisualBrush, EdgeMode.Aliased);
RenderOptions.SetCachingHint(surrogateVisualBrush, CachingHint.Cache);
directVisualBrush.Stretch = Stretch.None;
surrogateVisualBrush.ViewboxUnits = BrushMappingMode.Absolute;
surrogateVisualBrush.ViewportUnits = BrushMappingMode.RelativeToBoundingBox;
surrogateVisualBrush.Viewport = new Rect(0, 0, 1, 1);
}
public static readonly DependencyProperty VisualProperty = DependencyProperty.Register("Visual",
typeof(Visual), typeof(GlassBehavior), new FrameworkPropertyMetadata(
null, new PropertyChangedCallback(OnVisualChanged)));
public Visual Visual
{
get { return (Visual)GetValue(VisualProperty); }
set { SetValue(VisualProperty, value); }
}
private static void OnVisualChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((GlassBehavior)d).OnVisualChanged(e);
}
protected virtual void OnVisualChanged(DependencyPropertyChangedEventArgs e)
{
SetupVisual();
}
public static readonly DependencyProperty EffectProperty =
DependencyProperty.Register("Effect", typeof(Effect), typeof(GlassBehavior),
new FrameworkPropertyMetadata(null,
new PropertyChangedCallback(OnEffectChanged)));
public Effect Effect
{
get { return (Effect)GetValue(EffectProperty); }
set { SetValue(EffectProperty, value); }
}
private static void OnEffectChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((GlassBehavior)d).OnEffectChanged(e);
}
protected virtual void OnEffectChanged(DependencyPropertyChangedEventArgs e)
{
SetEffect();
}
private void SetEffect()
{
if (surrogateVisual == null)
return;
surrogateVisual.Effect = Effect;
}
private void SetupVisual()
{
var element = Visual as FrameworkElement;
if (element == null || attachedObject == null)
return;
SetEffect();
surrogateVisualBrush.Visual = element;
surrogateVisual.Fill = surrogateVisualBrush;
directVisualBrush.Visual = surrogateVisual;
EnsureBrushSyncWithVisual();
}
private void EnsureBrushSyncWithVisual()
{
if (attachedObject == null || Visual == null)
return;
surrogateVisual.Width = attachedObject.ActualWidth;
surrogateVisual.Height = attachedObject.ActualHeight;
GeneralTransform trans = attachedObject.TransformToVisual(Visual);
Point pos = trans.Transform(new Point(0, 0));
var viewbox = new Rect
{
X = pos.X,
Y = pos.Y,
Width = attachedObject.ActualWidth,
Height = attachedObject.ActualHeight
};
surrogateVisualBrush.Viewbox = viewbox;
}
protected override void OnAttached()
{
if (attachedObject != null)
attachedObject.LayoutUpdated -= AssociatedObject_LayoutUpdated;
attachedObject = AssociatedObject;
PropertyInfo info = FindFillProperty(attachedObject);
if (info != null)
info.SetValue(attachedObject, directVisualBrush, null);
attachedObject.LayoutUpdated += AssociatedObject_LayoutUpdated;
SetupVisual();
base.OnAttached();
}
protected override void OnDetaching()
{
if (attachedObject != null)
attachedObject.LayoutUpdated -= AssociatedObject_LayoutUpdated;
base.OnDetaching();
}
private static PropertyInfo FindFillProperty(DependencyObject obj)
{
Type t = obj.GetType();
PropertyInfo info = t.GetProperty("Background") ?? t.GetProperty("Fill");
return info;
}
private void AssociatedObject_LayoutUpdated(object sender, EventArgs e)
{
EnsureBrushSyncWithVisual();
}
}
I then have the following XAML to adopt this effect
<Window ...>
<Grid>
<Grid x:Name="G0">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="G1"
Margin="0,0,0,0"
Canvas.Left="0"
Canvas.Top="0"
Width="{Binding ActualWidth, ElementName=C1}"
Height="{Binding ActualHeight, ElementName=C1}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Image Source="large-snow-leopard-portrait-chris-boulton.jpg"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Stretch="UniformToFill"/>
</Grid>
<Border Margin="479,10,10,10"
Background="#FF545454"
BorderBrush="#FF000000"
BorderThickness="1,1,1,1"
CornerRadius="8,8,8,8">
<i:Interaction.Behaviors>
<Behaviors:GlassBehavior Visual="{Binding ElementName=G1, Mode=OneWay}">
<Behaviors:GlassBehavior.Effect>
<BlurEffect/>
<!--<ShaderEffectLibrary:PixelateEffect HorizontalPixelCounts="40" VerticalPixelCounts="40"/>-->
</Behaviors:GlassBehavior.Effect>
</Behaviors:GlassBehavior>
</i:Interaction.Behaviors>
<Border.Effect>
<DropShadowEffect BlurRadius="20" ShadowDepth="1"/>
</Border.Effect>
<Grid HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Content="Button" Margin="30,0" Height="30"/>
<Button Grid.Row="1" Content="Button" Margin="30,0" Height="30"/>
<Button Grid.Row="2" Content="Button" Margin="30,0" Height="30"/>
<Button Grid.Row="3" Content="Button" Margin="30,0" Height="30"/>
</Grid>
</Border>
</Grid>
</Grid>
</Window>
This produces
This is great, but I want to apply this blur to a movable ContentControl I am using so that I can drag my control over an image, and blur/redact someones face, in order to turn this image
into this image (note the blurry face).
To do this, I attempt to add a Canvas to the above XAML, and we have
...
<Grid>
<Grid x:Name="G0">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="G1"
Margin="0,0,0,0"
Canvas.Left="0"
Canvas.Top="0"
Width="{Binding ActualWidth, ElementName=C1}"
Height="{Binding ActualHeight, ElementName=C1}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Image Source="large-snow-leopard-portrait-chris-boulton.jpg"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Stretch="UniformToFill"/>
</Grid>
<Canvas x:Name="C1"
Panel.ZIndex="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<ContentControl
Width="130"
Height="130"
Canvas.Top="150"
Canvas.Left="150"
Selector.IsSelected="True"
Controls:TextBoxAttachedProperties.Text="Some Text Person #2"
Controls:TextBoxAttachedProperties.TextBoxBackground="DeepPink"
Controls:TextBoxAttachedProperties.TextBoxForeground="White"
Controls:ResizeThumb.HandleForeground="#2D2D30"
Controls:ResizeThumb.HandleForegroundHovered="#007ACC"
Controls:RotateThumb.HandleVisibility="Collapsed"
Controls:RotateThumb.HandleForeground="#656565"
Controls:RotateThumb.HandleForegroundHovered="#007ACC"
Style="{StaticResource MoveResizeRotateItemStyle}">
<Border Background="#FF545454" >
<i:Interaction.Behaviors>
<Behaviors:GlassBehavior Visual="{Binding ElementName=G1, Mode=OneWay}">
<Behaviors:GlassBehavior.Effect>
<ShaderEffectLibrary:PixelateEffect HorizontalPixelCounts="40" VerticalPixelCounts="40"/>
</Behaviors:GlassBehavior.Effect>
</Behaviors:GlassBehavior>
</i:Interaction.Behaviors>
</Border>
</ContentControl>
</Canvas>
</Grid>
</Grid>
</Window>
The problem is, I get an InvalidOperationException thrown from
GeneralTransform trans = attachedObject.TransformToVisual(Visual);
in the method EnsureBrushSyncWithVisual() of the GlassBehavior class.
System.InvalidOperationException: 'The specified Visual and this Visual do not share a common ancestor, so there is no valid transformation between the two Visuals.'
My question is
Q. How can I edit the GlassBehavior class so that I can apply this effect to my movable ContentControl, so that the moved control casts the desired blur on the hovered image?
[I'm sorry for my bad English]
In my MainWindow I have some ContentControl and I set his Content to some view called SimpleView. If that SimpleView has ListBox bounded to Collection, The view is alive even if I remove the SimpleView.
All my viewmodels are Implementing INotifyPropertyChanged.
This is my code:
MainWindow.xaml
<Window x:Class="WpfMemory.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 Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button Content="Set view" Click="SetView" />
<Button Content="Clear view" Click="ClearView" />
</StackPanel>
<ContentControl x:Name="ViewContainer" Grid.Row="1" Margin="4" />
</Grid>
</Window>
In code behind
private void SetView(object sender, RoutedEventArgs e)
{
var simpleViewModel = new ViewModels.SimpleViewModel();
var simpleview = new Views.SimpleView() { DataContext = simpleViewModel };
ViewContainer.Content = simpleview;
}
private void ClearView(object sender, RoutedEventArgs e)
{
ViewContainer.Content = null;
System.GC.Collect();
}
SampleView.xaml
<UserControl x:Class="WpfMemory.Views.SimpleView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition MinWidth="60"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="SomeText" />
<TextBox Text="{Binding SomeText}" Grid.Column="1"/>
<TextBlock Text="Large data" Grid.Row="1"/>
<ListBox ItemsSource="{Binding LargeData,Mode=OneTime}"
Grid.Row="2" Grid.Column="1"
DisplayMemberPath="Name" />
</Grid>
</UserControl>
View models
public sealed class SimpleViewModel : ViewModelBase
{
public SimpleViewModel()
{
var items = Enumerable.Range(1, 10000)
.Select(x => new SimpleItem()
{
Id = x,
Name = "Item " + x
})
.ToArray();
LargeData = new ObservableCollection<SimpleItem>(items);
}
public string SomeText{ get; set; } = "yehudah";
ObservableCollection<SimpleItem> largeData;
public ObservableCollection<SimpleItem> LargeData
{
get { return largeData; }
set { SetProperty(ref largeData, value); }
}
}
public sealed class SimpleItem : ViewModelBase
{
public int Id { get; set; }
public string Name { get; set; }
}
I run the application and Click on SetView and then on ClearView.
Now, in vs diagnostic tools I click on "Take snapshot" And this is the result:
Thanks for any help.
I think you should reset simpleview.DataContext when content control is unloaded.
You can do
simpleview.Unloaded += (_, __) => simpleview.DataContext = null;
when SetView.
can I create something like this in silverlight? A box with editable title and the rest of the text
http://docs.jboss.org/seam/3/latest/reference/en-US/html/images/remoting-model-customer-address-uml.png
You could create a custom user control:
XAML:
<UserControl x:Class="WpfApplication1.MyBox"
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="300" d:DesignWidth="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox Text="{Binding Header,UpdateSourceTrigger=PropertyChanged}"
BorderBrush="Black" BorderThickness="1" Margin="2" />
<TextBox Text="{Binding Text,UpdateSourceTrigger=PropertyChanged}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto"
AcceptsReturn="True"
BorderBrush="Black" BorderThickness="1" Margin="2" Grid.Row="1" />
</Grid>
</UserControl>
Code behind:
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication1
{
public partial class MyBox : UserControl
{
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register("Header", typeof(string), typeof(MyBox));
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Content", typeof(string), typeof(MyBox));
public string Header
{
get { return GetValue(HeaderProperty) as string; }
set { SetValue(HeaderProperty, value); }
}
public string Text
{
get { return GetValue(TextProperty) as string; }
set { SetValue(TextProperty, value); }
}
public MyBox()
{
InitializeComponent();
this.DataContext = this;
}
}
}
A sample:
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"
xmlns:local="clr-namespace:WpfApplication1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<local:MyBox x:Name="box1" Header="Type a header..." Text="Type a content..." Grid.Row="0" Grid.Column="0" BorderBrush="Black" BorderThickness="1" Margin="10" />
<local:MyBox x:Name="box2" Header="Type a header..." Text="Type a content..." Grid.Row="0" Grid.Column="1" BorderBrush="Black" BorderThickness="1" Margin="10" />
<Button Content="Show" Grid.Row="1" Grid.Column="0" Click="Button_Click" />
</Grid>
</Window>
Code behind:
using System.Windows;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(string.Format("{0}\n{1}\n\n{2}\n{3}", box1.Header, box1.Text, box2.Header, box2.Text));
}
}
}
This is WPF but should be fine in Silverlight too, except the MessageBox stuff but it's only for debugging purposes...
EDIT:
Here is a sample for dynamic generation:
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"
xmlns:local="clr-namespace:WpfApplication1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel x:Name="panel" Orientation="Horizontal">
<local:MyBox x:Name="box1" Header="Type a header..." Text="Type a content..." Grid.Row="0" Grid.Column="0" BorderBrush="Black" BorderThickness="1" Margin="10" />
</StackPanel>
<Button Content="Add" Grid.Row="1" Grid.Column="0" Click="Button_Click" />
</Grid>
</Window>
CodeBehind:
using System.Windows;
using System.Windows.Media;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
panel.Children.Add(new MyBox
{
Header = "Another box",
Text = "...",
BorderBrush = Brushes.Black,
BorderThickness = new Thickness(1),
Margin = new Thickness(10)
});
}
}
}
I am developing a UserControl that consists of a block with a heading and a list of items (ItemsControl). The problem is that the user control contents gets clipped off when I dynamically add the usercontrol to a canvas as shown below. I am not setting a size for the usercontrol internally. What can be done to avoid this.
Clipping is happening even when I drag and drop the usercontrol to canvas. I need the contents to get scaled.
<UserControl x:Class="MyTools.MyControl"
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"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid x:Name="LayoutRoot" Background="White">
<Border Name="MainBorder" CornerRadius="5" BorderThickness="2" BorderBrush="Black">
<Grid Name="grid1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" >
<Grid.RowDefinitions>
<RowDefinition Height="34" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Name="titleGrid" Grid.Row="0" Background="#FF727272">
<TextBlock Name="titleText" HorizontalAlignment="Center" Text="{Binding ControlName}" VerticalAlignment="Center" FontSize="13" FontWeight="Bold" Foreground="Beige" />
</Grid>
<Grid Name="gridpr" Grid.Row="1" Background="#12C48F35">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Name="borderPr" CornerRadius="3" Margin="10" BorderThickness="1" BorderBrush="LightGray" Grid.Row="0">
<Grid Name="gridPr" Background="#FFC1C1C1" MouseLeftButtonUp="gridPr_MouseLeftButtonUp">
<StackPanel>
<TextBlock HorizontalAlignment="Center" Name="txtPr" Text="SubItems" VerticalAlignment="Center" Foreground="#FF584848" FontSize="12" />
<ItemsControl x:Name="pitems" ItemsSource="{Binding MyItems}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="15,0,0,0">
<TextBlock Text="{Binding MyVal}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
</Border>
</Grid>
</Grid>
</Border>
</Grid>
</UserControl>
Code-behind for UserControl:
namespace MyTools
{
public partial class MyControl : UserControl
{
public MyControl()
{
InitializeComponent();
}
public string ControlName { get; set; }
public object MyItems { get; set; }
public class Row
{
public string MyVal { get; set; }
}
protected override Size MeasureOverride(Size availableSize)
{
var desiredSize = base.MeasureOverride(availableSize);
var sideLength = Math.Min(desiredSize.Width, desiredSize.Height);
desiredSize.Width = sideLength;
desiredSize.Height = sideLength;
return desiredSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
var sideLength = Math.Min(this.DesiredSize.Width, this.DesiredSize.Height);
return base.ArrangeOverride(new Size(sideLength, sideLength));
}
private void gridPr_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
pitems.Visibility = pitems.Visibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
}
}
}
Host Client Code:
namespace TestProject
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
MyControl control1 = new MyControl();
control1.ControlName = "Test Name";
var test = new List<MyControl.Row>(
new MyControl.Row[]
{
new MyControl.Row {MyVal = "Item1"},
new MyControl.Row {MyVal = "Item2"},
new MyControl.Row {MyVal = "Item3"}
});
control1.MyItems = test;
control1.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
MessageBox.Show(control1.DesiredSize.Height.ToString());
canvas1.Children.Add(control1);
}
}
}
Layout of host:
<UserControl x:Class="TestProject.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"
mc:Ignorable="d"
d:DesignHeight="503" d:DesignWidth="758" xmlns:my="clr-namespace:MyTools">
<Grid x:Name="LayoutRoot" Background="White" Height="507" Width="757">
<Canvas Height="503" Name="canvas1" HorizontalAlignment="Left" Margin="-1,-1,0,0" VerticalAlignment="Top" Width="758">
</Canvas>
</Grid>
</UserControl>
EDIT:
Turns out that the issue is because of MeasureOverride. The clipping is not there when I removed it. Thanks for the suggestions.