Animate control with respecting parents/container - wpf

I have a control that I move with help of animation from the bottom to the final position. My problem is now that I want to change the behaviour of the animation, so that it respects the outer container (DarkGray).
The orange Ractangle should only be visible on the white background and not on the darkgray Grid!
Code:
MainWindow.xaml:
<Grid Background="DarkGray">
<Grid Margin="50"
Background="White">
<Rectangle x:Name="objectToMove"
VerticalAlignment="Bottom"
Fill="Orange"
Height="50"
Width="50"/>
<Button Height="20"
Width="40"
Margin="20"
Content="Move"
Click="Button_Click"
VerticalAlignment="Top"/>
</Grid>
</Grid>
MainWindow.xaml.cs:
private void Button_Click(object sender, RoutedEventArgs e)
{
var target = objectToMove;
var heightOfControl = target.ActualHeight;
var trans = new TranslateTransform();
target.RenderTransform = trans;
var myAnimation = new DoubleAnimation(heightOfControl, 0, TimeSpan.FromMilliseconds(600));
trans.BeginAnimation(TranslateTransform.YProperty, myAnimation);
}
Current:
Desired solution:

Use ClipToBounds Property for this.
<Grid Margin="50"
Background="White"
ClipToBounds="True">

Related

UserControl child fill Window

I have a UserControl that is a portion of a wpf window.
<Window>
<Grid>
<!--some other display elements would be here-->
<local:MyUserControl x:Name="Foo" Padding="0,42,0,50"/>
</Grid>
</Window>
Inside MyUserControl I have an element that is a gallery that is normally hidden, but when visible, it should fill the entire screen.
<UserControl>
<Grid>
<!--main display elements would be here-->
<Grid Name="Gallery" Visibility="Hidden">
<Rectangle Fill="Black" Opacity="0.75"/>
<TextBlock Name="GalleryLabel" Foreground="White" TextAlignment="Center">Current Image Title</TextBlock>
<Button Name="CloseGallery" Style="{DynamicResource WhiteTextButton}" Margin="0,0,0,0" Height="25" VerticalAlignment="Top" HorizontalAlignment="Right" Width="25" Click="GalleryClose_OnClick">X</Button>
<Image Name="GalleryImage" Margin="25"/>
</Grid>
</Grid>
</UserControl>
How can I set the Gallery to fill the entire Window rather than just the UserControl?
I was able to get it to work by adding Margin="0,-42,0,-50" to Gallery, but I don't like that solution. I would rather do something that doesn't involve hard-coding values in the UserControl so that I would be able to have more flexiblility in using it.
Normally it looks like:
where the green Foo area is MyUserControl, and the rest of the things in the window are other elements.
At certain points, I have a gallery display an image, which should fill the entire screen like:
which should fill the entire screen and have a black opaque overlay, along with an image displayed on top of the overlay.
Remove the Padding...
You can use:
<local:MyUserControl x:Name="Foo" VerticalAlignment="Stretch" HorizontalAligment="Stretch"/>
EDIT
I may admit that I still am not sure what you want. But I made something which does the same as you showed in the pictures. But be aware that this as an opinion based question, and the answer is my opinion, there are a lot of ways to achieve this. And this is only one of them:
MainWindow
<Window x:Class="MyProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myProject="clr-namespace:MyProject"
Title="MainWindow" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border Background="Gainsboro" Grid.Row="0">
<StackPanel Orientation="Horizontal">
<Button Content="Show gallery" Width="100" Margin="10"/>
<Button Content="Do something else" Width="150" Margin="10"/>
</StackPanel>
</Border>
<myProject:SomeOtherStuff Grid.Row="1" />
<Border Grid.Row="2" Background="Gainsboro">
<StackPanel Orientation="Horizontal">
<Label Content="Buttom area, can be used for something else"/>
</StackPanel>
</Border>
<myProject:GalleryUserControl x:Name="GalleryUserControl" Grid.Row="0" Grid.RowSpan="3" Visibility="Hidden"/>
</Grid>
SomeOtherStuff UserControl
<UserControl x:Class="MyProject.SomeOtherStuff"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid Background="Green">
<Label VerticalAlignment="Center" HorizontalAlignment="Center" Content="Foo" FontSize="30" FontFamily="Verdana"/>
</Grid>
Gallery UserControl
<UserControl x:Class="XamDataGrid.GalleryUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="500" Width="800">
<Grid Background="#99000000">
<TextBlock Text="Currect image title" Foreground="White" TextAlignment="Center" VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
<Button Name="CloseGallery" Margin="0,0,0,0" Content="X" Height="25" VerticalAlignment="Top" HorizontalAlignment="Right" Width="25" Click="GalleryClose_OnClick"/>
<Image Margin="30"/>
</Grid>
An Adorner will be best for you. As it floats above everything else and remains outside the VisualTree too.
UserControl2
<UserControl2 ...>
<Grid>
<Grid Background="#FF709FA6" Opacity="0.3" Width="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}"
Height="{Binding ActualHeight, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}">
</Grid>
<Grid Width="600" Height="700">
<Grid.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF37DAEA" Offset="0"/>
<GradientStop Color="#FFE84242" Offset="1"/>
</LinearGradientBrush>
</Grid.Background>
<!-- Gallery controls -->
<Button Content="Welcome to Gallery" HorizontalAlignment="Left" IsHitTestVisible="True" Margin="112,126,0,0" VerticalAlignment="Top" Height="68" FontSize="48" Click="Button_Click_1"/>
<TextBlock HorizontalAlignment="Left" Margin="83,42,0,0" TextWrapping="Wrap" Text="UserControl2" VerticalAlignment="Top" Foreground="#FF1B0D0D"/>
</Grid>
</Grid>
</UserControl2>
UserControl1
Code :
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
// get root Window
DependencyObject current = LogicalTreeHelper.GetParent(this);
while (!(current is Window))
current = LogicalTreeHelper.GetParent(current);
Window root = current as Window;
IEnumerable children = LogicalTreeHelper.GetChildren(root);
Panel p = null;
foreach (var child in children)
{
p = child as Panel; // get first container panel in Window
break;
}
// Create UserControl2 to add to the adorner
UserControl2 ctrlGallery = new UserControl2();
AdornerLayer layer = AdornerLayer.GetAdornerLayer(p);
GalleryAdorner adorner = new GalleryAdorner(p, ctrlGallery);
layer.Add(adorner);
}
}
public class GalleryAdorner : Adorner
{
private Control _child;
VisualCollection collection;
public GalleryAdorner(UIElement elem, Control child)
: base(elem)
{
collection = new VisualCollection(this);
_child = child;
collection.Add(_child);
}
protected override int VisualChildrenCount
{
get
{
return 1;
}
}
protected override Visual GetVisualChild(int index)
{
if (index != 0) throw new ArgumentOutOfRangeException();
return collection[0];
}
protected override Size MeasureOverride(Size constraint)
{
_child.Measure(constraint);
return _child.DesiredSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
_child.Arrange(new Rect(new Point(0, 0), finalSize));
return new Size(_child.ActualWidth, _child.ActualHeight);
}
}

How control re-position depends on other control visibility in same panel

I have two buttons inside a stack panel. Initially B1 button is on top, then B2. I will change button visibility dynamically from code so that, when I change B1 visibility hidden, then B2 will come on top. How can I achieve this functionality.
<Grid>
<StackPanel >
<Button Content="B1" Height="20" Width="100" Visibility="Visible"/>
<Button Content="B2" Height="20" Width="100" Visibility="Visible"/>
</StackPanel>
</Grid>
First you remove the Statckpanel and put then in a Grid and you can achieve
Try something like this.
<Grid>
<Button Content="B1" Height="20" Width="100" Visibility="Visible" Click="Button_Click" x:Name="B1" />
<Button Content="B2" Height="20" Width="100" Visibility="Visible" x:Name="B2" Click="B2_Click" />
</Grid>
private void Button_Click(object sender, RoutedEventArgs e)
{
B1.Visibility = System.Windows.Visibility.Hidden;
B2.Visibility = System.Windows.Visibility.Visible;
}
private void B2_Click(object sender, RoutedEventArgs e)
{
B2.Visibility = System.Windows.Visibility.Hidden;
B1.Visibility = System.Windows.Visibility.Visible;
}
This should give you similar behaviour. Change according to your use

Silverlight 4: how to show ToolTip on keyboard focus (revised)

My original question:
Is there an easy way for a ToolTip to be shown when an item gets keyboard focus, not just mouse over? We have a list of items with tooltips that users will probably tab through, and the desired behavior is for a tooltip to be shown then too.
Added example XAML. A HyperlinkButton with the Tooltip set is what needs the keyboard focus as well.
<DataTemplate x:Key="OfferingItemDT">
<HyperlinkButton Command="{Binding Path=NavigateToLinkCommand}" ToolTipService.ToolTip="{Binding Tooltip}">
<Grid x:Name="gOfferingButtonRoot" Width="275" MaxHeight="78" Margin="5,3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Image x:Name="imgServiceOfferingIcon"
Grid.RowSpan="2"
VerticalAlignment="Top"
Source="{Binding Path=Image, Converter={StaticResource ByteArrayToImageConverter}}"
Stretch="UniformToFill"
Margin="2,10,0,0"
MaxHeight="32" MaxWidth="32"
/>
<TextBlock x:Name="txbOfferingTitle"
Grid.Column="1"
Grid.Row="0"
Text="{Binding Title}"
TextWrapping="Wrap"
Style="{StaticResource OfferingTileTitleText}"/>
<TextBlock x:Name="txbOfferingDesc"
Grid.Column="1"
Grid.Row="1"
Style="{StaticResource OfferingTileBodyText}"
Text="{Binding BriefDescription}" />
</Grid>
</HyperlinkButton>
</DataTemplate>
Updated:
Based on info in WPF: Show and persist ToolTip for a Textbox based on the cursor as well as Anthony's comments, I tried this code in the GotFocus eventhandler:
private void showTooltip(object sender, RoutedEventArgs e)
{
HyperlinkButton hb = new HyperlinkButton();
ToolTip ttip = new ToolTip();
hb = sender as HyperlinkButton;
ttip = ToolTipService.GetToolTip(hb) as ToolTip;
ttip.IsOpen = true;
}
This seems like it would work, but ttip is always null. Help?
"Easy" is subjective term. Yes its easy. On the same UI element on which you attach the ToolTip you can hook the GotFocus and LostFocus event handler the will use ToolTipService.GetToolTip to acquire the tooltip and the set IsOpen to true and false respectively.
The missing part is to define the tooltip in XAML so that we can access the Tooltip element.
<HyperlinkButton MouseLeftButtonUp="showTooltip">
<ToolTipService.ToolTip>
<ToolTip>
<TextBlock Text="My tooltip text"/>
</ToolTip>
</ToolTipService.ToolTip>
<!-- ... -->
</HyperlinkButton>
Code behind
private void showTooltip(object sender, RoutedEventArgs e)
{
FrameworkElement frameworkElement = (FrameworkElement)sender;
ToolTip tooltip = ToolTipService.GetToolTip(frameworkElement) as ToolTip;
if (tooltip != null)
{
tooltip.IsOpen = true;
frameworkElement.MouseLeave += new MouseEventHandler(frameworkElement_MouseLeave);
}
}
static void frameworkElement_MouseLeave(object sender, MouseEventArgs e)
{
FrameworkElement frameworkElement = (FrameworkElement)sender;
frameworkElement.MouseLeave -= new MouseEventHandler(frameworkElement_MouseLeave);
ToolTip tooltip = ToolTipService.GetToolTip(frameworkElement) as ToolTip;
if (tooltip != null)
{
tooltip.IsOpen = false;
}
}

Changing RenderTransformOrigin property of rotated object

how can I make a rotated object stand still when its RenderTransformOrigin property is changed? After running the code below, you can notice by rotating the object (the slider does that), changing the origin of rotation (the button) and rotating it again, that the object slightly moves. What I'm trying to achieve is being able to rotate the object against different points without it moving around whenever I try to switch between them.
<UserControl x:Class="ObjrctRotation.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="300" d:DesignWidth="400">
<Canvas x:Name="C" Background="White">
<Path x:Name="thing" RenderTransformOrigin="0,0" Stretch="Fill" Stroke="Black" StrokeThickness="2" Height="93.153" HorizontalAlignment="Left" VerticalAlignment="Top" Width="106.357" UseLayoutRounding="False" Data="M48.723255,124.82815 C41.00029,80.999809 81.000046,65.000069 112.99985,89.000092 C144.99965,113.00011 168.9996,169.00061 136.99989,169.0002 C105.00018,168.99979 104.9999,145.00015 81.000053,145.00015 C57.000206,145.00015 56.44622,168.65649 48.723255,124.82815 z" Canvas.Left="69" Canvas.Top="24" />
<Slider Value="0" Minimum="0" Maximum="360" Width="100" Margin="300,0,0,272" ValueChanged="Slider_ValueChanged" />
<TextBlock x:Name="test" Width="100" Height="20" Canvas.Left="300" Canvas.Top="24" />
<Button Canvas.Left="300" Canvas.Top="24" Content="ChangeCenter" Height="20" Name="button1" Width="100" Click="button1_Click"/>
</Canvas>
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
RotateTransform rotate = new RotateTransform()
{
Angle=e.NewValue
};
thing.RenderTransform = rotate;
}
private void button1_Click(object sender, RoutedEventArgs e)
{
thing.RenderTransformOrigin = new Point(thing.RenderTransformOrigin.X + 0.2, thing.RenderTransformOrigin.Y + 0.2);
}
}
Set the RenderTransformOrigin="0,0" to RenderTransformOrigin="0.5,0.5" so that the transform origin is in the middle of the object you wish to rotate.

How to access Button programatically if the button is inside using C#

I have few questions as I am usign XAML for the first time.
How do I use the button (BrowseButton) to browse a folder in Harddrive ?
In this case as the button is inside
Can I use the way I have shown below?
Actually first dockpanel will hold the image and some label and the other dockpanel will have tabcontrol in it.
If I have a tabcontrol, How can I add a listview which can increase the tabs during runtime.. and the listview should be available in the runtime also.
How to add a close("X") mark on the top of the tab to close the button
probably I asked a lot of questions, sorry :(
Please help
<Grid>
<DockPanel>
<StackPanel>
<Image Name="imgClientPhoto" HorizontalAlignment="Left" VerticalAlignment="Top" Width="auto" Height="auto" Grid.Column="0" Grid.Row="0" Margin="0"
Source="D:ehtmp_top_left.gif" MinWidth="450" MinHeight="100" Grid.IsSharedSizeScope="True">
</Image>
<Button x:Name="BrowseButton" Margin="0,13.638,30,14.362" Content="Browse" Click="BrowseButton_Click" HorizontalAlignment="Right" Width="111" />
<TextBox x:Name="txtBxBrowseTB" Margin="46,10,146,10" Text="TextBox" TextWrapping="Wrap" TextChanged="BrowseTB_TextChanged"></TextBox>
<Label HorizontalAlignment="Left" Margin="-14,22,0,10" Name="label1" Width="69.75" FontSize="13" VerticalContentAlignment="Top" HorizontalContentAlignment="Center">Path:</Label>
</Grid>
</GroupBox>
</Grid>
</StackPanel>
</DockPanel>
<DockPanel>
<StackPanel Margin="0,158,0,0" HorizontalAlignment="Left" Width="330" Height="557.5" VerticalAlignment="Top">
<TextBox Height="50" Name="textBox1" Width="240" Margin="0,35,0,0" VerticalAlignment="Stretch" HorizontalAlignment="Right" />
<ListBox Height="470" Name="listBox1" Width="332" Background="LightGray" Margin="0,0,0,0" BorderBrush="IndianRed" BorderThickness="3" />
</StackPanel>
<TabControl Height="234" Name="tabControl1" Width="1035" Margin="0,0,0,0">
<TabItem Header="tabItem1" Name="tabItem1">
<Grid Height="144" />
</TabItem>
</TabControl>
</DockPanel>
</Grid>
1) The browse code should be something like this:
private void BrowseButton_Click(object sender, RoutedEventArgs e)
{
System.Windows.Forms.FolderBrowserDialog browse = new System.Windows.Forms.FolderBrowserDialog();
browse.RootFolder= Environment.SpecialFolder.MyDocuments;
browse.SelectedPath = "C:\\InitalFolder\\SomeFolder";
if (browse.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
txtBxBrowseTB.Text = browse.SelectedPath;
}
}
2) I have tried to simplify the xaml. Does this look like something you could go with?:
<Grid>
<Image Name="imgClientPhoto" Margin="0" Height="262" VerticalAlignment="Top" HorizontalAlignment="Left" ></Image>
<StackPanel VerticalAlignment="Stretch" >
<StackPanel VerticalAlignment="Top" Orientation="Horizontal" Height="30">
<Button Name="BrowseButton" Content="Browse" Click="BrowseButton_Click" HorizontalAlignment="Right" Width="111" />
<Label Name="label1" Width="69.75" FontSize="13" VerticalContentAlignment="Center" HorizontalContentAlignment="Right">Path:</Label>
<TextBox Name="txtBxBrowseTB" Width="200" Text="TextBox" VerticalContentAlignment="Center" TextWrapping="Wrap" TextChanged="BrowseTB_TextChanged"></TextBox>
</StackPanel>
<StackPanel>
<StackPanel Orientation="Vertical">
<TextBox Height="50" Name="textBox1" />
<ListBox Height="470" Name="listBox1" Background="LightGray" Margin="0,0,0,0" BorderBrush="IndianRed" BorderThickness="3" MouseLeftButtonUp="listBox1_MouseLeftButtonUp">
<ListBoxItem>User1</ListBoxItem>
<ListBoxItem>User2</ListBoxItem>
<ListBoxItem>User3</ListBoxItem>
<ListBoxItem>User4</ListBoxItem>
</ListBox>
</StackPanel>
<TabControl Name="tabControl1" />
</StackPanel>
</StackPanel>
</Grid>
You can also have a close button in the tab item Header. As many of the content properties in xaml controls, the content can actually be controls, and not necessary just a text.
<TabControl Name="tabControl1" >
<TabItem Name="tabItem1" >
<TabItem.Header>
<StackPanel Orientation="Horizontal">
<Label>TabHeader1</Label>
<Button Height="20" Width="20" FontWeight="Bold" Click="CloseTabButton_Click">X</Button>
</StackPanel>
</TabItem.Header>
<Grid Height="144">
<ListView />
</Grid>
</TabItem>
</TabControl>
3) Here is how you would add the tabs in C# dynamically:
private void listBox1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
//Get selected item
ListBoxItem item = (ListBoxItem)listBox1.SelectedItem;
string itemText = item.Content.ToString();
//Check if item is already added
foreach (TabItem tItem in tabControl1.Items)
{
if ((string)tItem.Tag == itemText)
{
//Item already added, just activate the tab
tabControl1.SelectedItem = tItem;
return;
}
}
//Build new tab item
TabItem tabItem = new TabItem();
tabItem.Tag = itemText;
//First build the Header content
Label label = new Label();
Button button = new Button();
label.Content = itemText;
button.Content = "X";
button.Height = 20;
button.Width = 20;
button.FontWeight = FontWeights.Bold;
button.Click += CloseTabButton_Click; //Attach the event click method
button.Tag = tabItem; //Reference to the tab item to close in CloseTabButton_Click
StackPanel panel = new StackPanel();
panel.Orientation = Orientation.Horizontal;
panel.Children.Add(label);
panel.Children.Add(button);
tabItem.Header = panel;
//Then build the actual tab content
//If you need only the ListView in here, you don't need a grid
ListView listView = new ListView();
//TODO: Populate the listView with what you need
tabItem.Content = listView;
//Add the finished tabItem to your TabControl
tabControl1.Items.Add(tabItem);
tabControl1.SelectedItem = tabItem; //Activate the tab
}
private void CloseTabButton_Click(object sender, RoutedEventArgs e)
{
//The tab item was set to button.Tag when it was added
Button button = (Button)sender;
TabItem tabItem = (TabItem)button.Tag;
if (tabItem != null)
{
button.Click -= CloseTabButton_Click; //Detach event handler to prevent memory leak
tabControl1.Items.Remove(tabItem);
}
}

Resources