Add animation when user control get visible and collapsed In Wpf - c#

I have two xaml files MainWindow.xaml and other user control WorkDetail.xaml file.
MainWindow.xaml file has a textbox, button, listbox and reference to WorkDetail.xaml(user control which is collapsed). Whenever user enter any text, it gets added in listbox when the add button is clicked. When any items from the listbox is double clicked, the visibility of WorkDetail.xaml is set to Visible and it gets displayed. In WorkDetail.xaml (user control) it has textblock and button. The Textblock displays the text of selected item and close button sets the visibility of WorkDetail window to collapsed. Now i am trying to animate WorkDetail.xaml when it gets visible and collapse. When any items from listbox is double clicked and WorkDetail.xaml visibility is set to visible, i want to create an animation of moving WorkDetail.xaml window from right to left on MainWindow. When Close button from WorkDetail.xaml file is clicked and WorkDetail.xaml file is collapsed, i want to slide the WorkDetail.xaml file from left to right from MainWindow.
Here is the screenshot:
MainWindow.xaml code:
<Window...>
<Grid Background="Black" >
<TextBox x:Name="enteredWork" Height="39" Margin="44,48,49,0" TextWrapping="Wrap" VerticalAlignment="Top"/>
<ListBox x:Name="workListBox" Margin="26,155,38,45" FontSize="29.333" MouseDoubleClick="workListBox_MouseDoubleClick"/>
<Button x:Name="addWork" Content="Add" Height="34" Margin="71,103,120,0" VerticalAlignment="Top" Click="Button_Click"/>
<TestWpf:WorkDetail x:Name="WorkDetail" Visibility="Collapsed"/>
</Grid>
</Window>
MainWindow.xaml.cs class code:
namespace TestWpf
{
public partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
workListBox.Items.Add(enteredWork.Text);
}
private void workListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
WorkDetail.workTextBlk.Text = (string)workListBox.SelectedItem;
WorkDetail.Visibility = Visibility.Visible;
}
}
}
WorkDetail.xaml code:
<UserControl ..>
<Grid Background="#FFD2CFCF">
<TextBlock x:Name="workTextBlk" Height="154" Margin="33,50,49,0" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="29.333" Background="#FFF13939"/>
<Button x:Name="btnClose" Content="Close" Height="62" Margin="70,0,94,87" VerticalAlignment="Bottom" Click="btnClose_Click"/>
</Grid>
</UserControl>
WorkDetail.xaml.cs class code:
namespace TestWpf
{
public partial class WorkDetail : UserControl
{
public WorkDetail()
{
this.InitializeComponent();
}
private void btnClose_Click(object sender, System.Windows.RoutedEventArgs e)
{
Visibility = Visibility.Collapsed;
}
}
}
Can anyone tell how can i do this?

is this link interesting for you? I think that something very similar is accomplished using a VisualBrush based technique. It's worth a look!
JAPF http://www.remote-screenshots.com/thumbs/medium/0/www.japf.fr.jpg
Another idea would be using the VisualStateManager and Transistions: You can overwrite the style information of your controls and use Storyboard animations - without tools like Blend this could become very tricky, though.
Hope that helps anyway.
best regards,
thomas

Related

Creating UI element when user clicks in wpf

What I want to do is make it so when the user clicks the 'rectangle' shape it creates a white border around the box like so....
If the user clicks in an area where no rectangle is present then it deselects any selected rectangles. I'm assuming this may need some additional changes in the code, any suggestions are welcome!
I found a solution for you. Let me know if this works for you. If not I will try and modify it. It is basic, but not that hard to implement I believe.
Here is the XAML. Note you will have to do all the positioning of the rectangles and such yourself. This just selects and deselects with a black border.
<Grid Background="#00000000" MouseDown="Grid_MouseDown" >
<Border Visibility="Hidden" x:Name="border" BorderBrush="Black" BorderThickness="1" Margin="230,135,142,58">
</Border>
<Rectangle x:Name="rect" Fill="Blue" MouseDown="Rectangle_MouseDown" Margin="250,148,160,74"/>
</Grid>
And here is the code behind.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Rectangle_MouseDown(object sender, MouseButtonEventArgs e)
{
border.Visibility = Visibility.Visible;
}
private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.MouseDevice.DirectlyOver == rect)
{
}
else
{
border.Visibility = Visibility.Hidden;
}
}
}

WPF MDI maximize box

I'm using the WPF Multiple Document Interface from this site http://wpfmdi.codeplex.com/. How can I maximize the box inside the code the same way it is done when I click maximize button?
<DockPanel>
<mdi:MdiContainer Theme="Luna" DockPanel.Dock="Top" Margin="0 20 0 0" Name="MainMdiContainer">
<mdi:MdiChild Name="TestWindow" Title="Child Window" Background="AliceBlue" Resizable="True" />
</mdi:MdiContainer>
</DockPanel>
I've tried something like
TestWindow.WindowState = System.Windows.WindowState.Maximized;
but when I do so I cannot see the buttons I normally see when I press the Maximize button.
Your code works. Your problem must be somewhere else.
XAML :
<mdi:MdiContainer Grid.Column="2" x:Name="Container" Background="#bdbdbd" AllowDrop="True">
<mdi:MdiChild Name="TestWindow" Title="Child Window" Background="AliceBlue" Resizable="True" />
</mdi:MdiContainer>
C# :
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
TestWindow.MouseDown += TestResize;
}
private void TestResize(object sender, MouseButtonEventArgs e)
{
var mdiChild = sender as MdiChild;
if (mdiChild != null)
{
mdiChild.WindowState = WindowState.Maximized;
}
}
}
Note :
I use a modified version of WPF MDI because there is a bug in the mode maximized for the current version. The content height is bigger than the MdiChild content height.
I posted on codeplex a solution :
http://wpfmdi.codeplex.com/discussions/543694

Get event when user clicks away from current element or children

Okay, I have tried to use a popup to get this to work but there are a ton of reasons why that doesn't appear to be a route I want to take...especially because I've spent the last two hours trying to get it to work and I've deemed it unholier than all hell (this is despite the fact that I have popups in other places in the app that work just fine, but I digress...)
Basically I need only one piece of functionality that doesn't appear to be standard out of the box in WPF...I have to determine when someone clicks on something OTHER than a known UI element (I.E. they click away from something to close it...much like a popup set to StaysOpen = false)
From what I have gathered this is quite an arduous task and I can't seem to find a straight answer on the best way to do this...any ideas SO?
EDIT:
One of the commenters wanted me to post some sample code and re-reading through my question I really don't want to post something that is unrelated (the XY problem). I am posting this question for two reasons:
The onmouseleave event gets fired as soon as the popup opens. This means that if the popup is set to 'StaysOpen="False"' that the popup appears and immediately disappears no matter what. I believe wholeheartedly that this will not be an issue if I create a component that appears using the Visibility attribute to appear and disappear rather than placing it in a popup. The only reason I considered the popup component was because of it's StaysOpen=False functionality, not because it needs to float above everything else
The popup itself feels quite hacky, especially because it needs to fit inside of a parent component in the visual tree. As you can see from the code below, I have gotten the popup to fit inside of it's parent...but I really don't like binding a component's width and height to another component's actual width and height. This is the second reason I would like to avoid using a popup.
As a result, while this question could be 'how can I get the popup to work', the original question still stands: "How can I listen for a on click away event?" I would like to create a component that fits in the visual tree logically, and behaves as the following:
On hover over a component, appear
On leave a component disappear
On click on a component persist appearing
On click away from a component or itself close
I have all of the above handled except for on click away
How about the UIElement.LostFocus-Event? That seems to be the one you need.
I think in this case, you can be useful routed events. There are two types of events: Bubbling, Direct and Tunneling. Attention should be paid to Bubbling and Tunneling. Bubbling events rises up the logical tree and tunneling down. Below is a diagram from here:
So that event up / down the tree, it should be set on each control. Usually, the demonstration bubbling events, apply this example:
XAML
<Window x:Class="DemoRoutedEvents.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" MouseUp="somethingClicked">
<Grid MouseUp="somethingClicked">
<StackPanel MouseUp="somethingClicked" Margin="0,0,10,0">
<Label x:Name="btnClickMe" Content="Click Me!" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="101,22,0,0" MouseUp="somethingClicked"/>
<CheckBox x:Name="chkhandle" Content="CheckBox" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="241,28,0,0" RenderTransformOrigin="-0.588,1.188"/>
<ListBox x:Name="lstEvents" HorizontalAlignment="Left" Height="604" VerticalAlignment="Top" Width="416" Margin="29,66,0,0"/>
</StackPanel>
</Grid>
</Window>
Code behind
public int eventCounter = 0;
private void somethingClicked(object sender, RoutedEventArgs e)
{
eventCounter++;
String message = "#" + eventCounter.ToString() + ":\r\n" +
" Sender: " + sender.ToString() + ":\r\n" +
" Source: " + e.Source + ":\r\n" +
" Original Source: " + e.OriginalSource;
lstEvents.Items.Add(message);
e.Handled = (bool)chkhandle.IsChecked;
if (e.Handled)
lstEvents.Items.Add("Completed");
}
Output
I tried to optimize this process for multiple panels and components. I have created a attached dependency property IsDebugEvent, which is in the class of EventBehaviours. The principle is simple, we take an event handler and set it for all elements of the type Control (almost all the UIElements it inherits). For panels such as a Grid, StackPanel, WrapPanel, etc, Panel is the base class.
In the handler, we find ListBox and display the name of the panel s the element that caused the event, just for test. The example uses the event PreviewMouseLeftButtonDown (tunneling), because the first fires is an event at the Button.Click, and when it works, it conflicts with the event MouseUp. Quote from here:
ButtonBase inherits from UIElement, a Button will also have access to all of the mouse button events defined for UIElement. Because the Button does something in response to button presses, it swallows the bubbling events (e.g. MouseLeftButtonDown and MouseDown). You can still detect these lower level button press events by adding handlers for the tunneling events (e.g. PreviewMouseLeftButtonDown and PreviewMouseDown).
XAML
<Window x:Class="AwayEventHelp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:AwayEventHelp"
Title="MainWindow" Height="550" Width="525"
WindowStartupLocation="CenterScreen">
<Grid>
<CheckBox Name="DebugCheckBox" Width="100" Height="30"
VerticalAlignment="Top"
Content="Debug event" IsChecked="False"
Checked="DebugCheckBox_Checked" Unchecked="DebugCheckBox_Unchecked" />
<StackPanel Name="LeftStackPanel" Width="150" local:EventBehaviours.IsDebugEvent="False"
HorizontalAlignment="Left" Background="BlanchedAlmond">
<Button Name="LeftButton1" Height="30" Content="LeftButton1" />
<Button Name="LeftButton2" Height="30" Content="LeftButton2" />
<Button Name="LeftButton3" Height="30" Content="LeftButton3" />
<Label Name="JustLabelLeft" Content="JustLabelLeft" Background="Azure" HorizontalContentAlignment="Center" />
</StackPanel>
<StackPanel Name="RightStackPanel" Width="150" local:EventBehaviours.IsDebugEvent="False"
HorizontalAlignment="Right" Background="Azure">
<Button Name="RightButton1" Height="30" Content="RightButton1" />
<Button Name="RightButton2" Height="30" Content="RightButton2" />
<Button Name="RightButton3" Height="30" Content="RightButton3" />
<Label Name="JustLabelRight" Content="JustLabelRight" Background="BlanchedAlmond" HorizontalContentAlignment="Center" />
</StackPanel>
<Grid Name="GridPanel" Width="100" Height="100" local:EventBehaviours.IsDebugEvent="False"
VerticalAlignment="Bottom" Background="CadetBlue">
<Label Name="LabelInGrid" Width="100" Height="50" Content="LabelInGrid" Background="AliceBlue" />
</Grid>
<ListBox Name="EventOutput" Width="180" Height="180" Background="AliceBlue" />
</Grid>
</Window>
Code behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void DebugCheckBox_Checked(object sender, RoutedEventArgs e)
{
EventBehaviours.SetIsDebugEvent(LeftStackPanel, true);
EventBehaviours.SetIsDebugEvent(RightStackPanel, true);
EventBehaviours.SetIsDebugEvent(GridPanel, true);
}
private void DebugCheckBox_Unchecked(object sender, RoutedEventArgs e)
{
EventBehaviours.SetIsDebugEvent(LeftStackPanel, false);
EventBehaviours.SetIsDebugEvent(RightStackPanel, false);
EventBehaviours.SetIsDebugEvent(GridPanel, false);
}
}
public class EventBehaviours : DependencyObject
{
#region IsDebugEvent declaration
public static void SetIsDebugEvent(DependencyObject target, bool value)
{
target.SetValue(IsDebugEventProperty, value);
}
public static bool GetIsDebugEvent(DependencyObject DepObject)
{
return (bool)DepObject.GetValue(IsDebugEventProperty);
}
public static readonly DependencyProperty IsDebugEventProperty =
DependencyProperty.RegisterAttached("IsDebugEvent",
typeof(bool),
typeof(EventBehaviours),
new UIPropertyMetadata(false, OnIsDebugEvent));
#endregion
private static void OnIsDebugEvent(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
Panel MyPanel = sender as Panel;
if (e.NewValue is bool && ((bool)e.NewValue == true))
{
MyPanel.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(MyControl_PreviewMouseLeftButtonDown);
if (MyPanel.Children.Count != 0)
{
foreach (Control MyControl in MyPanel.Children)
{
MyControl.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(MyControl_PreviewMouseLeftButtonDown);
}
}
}
else
{
foreach (Control MyControl in MyPanel.Children)
{
MyControl.PreviewMouseLeftButtonDown -= new MouseButtonEventHandler(MyControl_PreviewMouseLeftButtonDown);
}
MyPanel.PreviewMouseLeftButtonDown -= new MouseButtonEventHandler(MyControl_PreviewMouseLeftButtonDown);
}
}
/// <summary>
/// Main handler of PreviewMouseLeftButtonDown event
/// </summary>
private static void MyControl_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
string OutInfo = string.Empty;
if (sender.GetType() == typeof(StackPanel))
{
StackPanel MyStackPanel = sender as StackPanel;
Grid MyGrid = MyStackPanel.Parent as Grid;
OutInfo = "PanelName: " + MyStackPanel.Name;
OutInfoInListBox(MyGrid, OutInfo);
}
else if (sender.GetType() == typeof(Grid))
{
Grid MyGrid = sender as Grid;
Grid MyMainGrid = MyGrid.Parent as Grid;
OutInfo = "PanelName: " + MyGrid.Name;
OutInfoInListBox(MyMainGrid, OutInfo);
}
else
{
Control MyControl = sender as Control;
Panel MyStackPanel = MyControl.Parent as Panel;
Grid MyGrid = MyStackPanel.Parent as Grid;
OutInfo = "ControlName: " + MyControl.Name;
OutInfoInListBox(MyGrid, OutInfo);
}
}
/// <summary>
/// Get ListBox and insert some info
/// </summary>
/// <param name="ParentGrid">Panel, where locate ListBox</param>
/// <param name="info">Just string</param>
private static void OutInfoInListBox(Grid ParentGrid, string info)
{
ListBox MyEventOutput = ParentGrid.FindName("EventOutput") as ListBox;
MyEventOutput.Items.Add(info);
}
}
Output
By clicking on the CheckBox, set a dependency property IsDebugEvent in True, subject thus causing OnIsDebugEvent, where we set the handlers. If you deselect the CheckBox in, then all event handlers deleted.
To set the events immediately on startup, you need to make sure that all the items on the successfully booted. This can be done in the event ContentRendered of Window.

Why isn't change button content working

I have this code:
private void ModifyButton_Click(object sender, RoutedEventArgs e)
{
ModifyButton.Content = "Another button name";
}
But it doesn't work. I mean, the modify button content doesn't change but the program doesn't fail or throw any exception.
I'm trying to modify the button name in order to change it's behavior (kinda Edit/Save) within the same button. Is this not possible using C#/WPF?
Thanks in advance.
EDIT:
XAML:
<Button Name="ModifyButton" Content="Modificar" Margin="5,10,0,0" Height="23" Width="120" HorizontalAlignment="Left" Click="ModifyButton_Click"></Button>
WEIRD BEHAVIOR: If I put a MessageBox.Show call after the change of the button content, then, while the message box is displayed the button dislay the new (changed) name, but after the message box is closed, then it shows it's original text.
I guess that the XAML of your UI is not bound to the value of your button. Did you check the DataBinding?
[EDIT]
Your magic information here is that you use ShowDialog(). As you already guessed, this influences your UI thread and therefore the display behavior. ShowDialog() displays the Form as a modal dialog and blocks your UI thread and therefore blocks the refresh of it. This may cause all sorts of weird behavior.
This is what i have and it works:
Window 1
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<Button Name="ModifyButton" Content="Open Dialog" Margin="80,104,78,0" Height="23" Click="ModifyButton_Click" VerticalAlignment="Top"></Button>
</Grid>
</Window>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void ModifyButton_Click(object sender, RoutedEventArgs e)
{
Window2 win2 = new Window2();
win2.ShowDialog();
}
}
Window 2
<Window x:Class="WpfApplication1.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window2" Height="300" Width="300">
<Grid>
<Button Name="ModifyButton" Content="Modificar" Margin="80,104,78,0" Height="23" Click="ModifyButton_Click" VerticalAlignment="Top"></Button>
</Grid>
</Window>
public partial class Window2 : Window
{
public Window2()
{
InitializeComponent();
}
private void ModifyButton_Click(object sender, RoutedEventArgs e)
{
ModifyButton.Content = "Another button name";
}
}

Programatically focus a UI element that was re-enabled in the prior statement

I'm developing a form and one of the requirements for it is that the majority of the fields be disabled until the first two have been completed. For the sake of usability I want it set up so after you tab out of the second field (Field_Two.LostFocus) the rest of the fields are enabled, displayed, and the first of those fields is focused. The code that I have currently sets all fields' visibility to visibility.hidden at startup. What it currently does is focus Field_One (next in the tab order of enabled fields), but I've confirmed that the conditions are properly satisfied and that execution proceeds past the return statement.
Field.beenFocused is a variable I've created that is initialized as false and then set to true when the Field is focused for the first time, my Field class extends TextBox; all of my controls save Field_One and Field_Two are in Stackpanels.
C#
void Field_Two_LostFocus(object sender, RoutedEventArgs e)
{
if (!Field_Three.beenFocused)
{
if (String.IsNullOrWhiteSpace(Field_One.Text) || String.IsNullOrWhiteSpace(Field_Two.Text))
return;
foreach (object u in ApplicationGrid.Children)
if (u.GetType() == typeof(StackPanel))
((StackPanel)u).IsEnabled = true;
do { Field_Three.Focus(); }
while (!Field_Three.beenFocused);
}
}
You could try enabling/disabling in a TextChanged event, rather than a LostFocus event.
Here's some sample code.
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">
<StackPanel>
<TextBox Name="textBox1" TextChanged="ValidateInitialFieldsOnChange"
Height="23" Width="120" />
<TextBox Name="textBox2" TextChanged="ValidateInitialFieldsOnChange"
Height="23" Width="120" />
<TextBox Name="textBox3" IsEnabled="False" Height="23" Width="120" />
</StackPanel>
</Window>
MainWindow.xaml.cs:
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ValidateInitialFieldsOnChange(object sender,
TextChangedEventArgs e)
{
textBox3.IsEnabled = !string.IsNullOrWhiteSpace(textBox1.Text)
&& !string.IsNullOrWhiteSpace(textBox2.Text)
;
}
}
}
It would be fairly trivial to adapt this code to suit your scenario, and wouldn't require manually setting focus. You could probably rely on tab order instead.
But if tab order doesn't help, you can still use a combination of these approaches to solve the problem. Set focus in the LostFocus event, and enable in teh TextChanged event.

Categories