Close current UserControl - wpf

I have a Window1.xaml main Window; and after some event, I display a UserControl EditFile.xaml.
The code behind is:
public static int whichSelected = -1;
private void button1_Click(object sender, RoutedEventArgs e)
{
//searchEditPanel.Children.Clear();
whichSelected = listViewFiles.SelectedIndex;
searchEditPanel.Children.Add(_EditFileControle); //this is Grid
}
And now, how can I close the opened/added UserControl from its content by clicking a Cancel button or something like that?

Window.GetWindow(this).Close();
You don't need to use a new variable, you can use it directly.

In your button click handler try :
Window parentWindow = (Window)this.Parent;
parentWindow.Close();

You could set the Visibility property of the control you want to "close" to Collapsed.
This way it will not be displayed anymore but will still be present in the visual tree if you need to reuse it later.

Have you tried this?
searchEditPanel.Children.Remove(_EditFileControle);
Another Suggestion:
Maybe this helps: http://sachabarber.net/?p=162
if it doesn't: Add a property to your UserControl:
public UserControl ParentControl {get;set;}
Now modify your code:
private void button1_Click(object sender, RoutedEventArgs e)
{
//searchEditPanel.Children.Clear();
whichSelected = listViewFiles.SelectedIndex;
_EditFileControle.ParentControl = this;
searchEditPanel.Children.Add(_EditFileControle); //this is Grid
}
Now you should be able to do this:
// Somewhere in your UserControl
if (this.ParentControl != null)
this.ParentControl.Children.Remove(this);

private void Button_Click(object sender, RoutedEventArgs e)
{
(this.Parent as searchEditPanel).Children.Remove(this);
}

Related

Why does WPFMediaKit VideoCaptureElement created by code land ever in MediaFailed?

I add a VideoCaptureElement to a window in runtime but when I run this code it fires MediaFailed. But if I add the same element in XAML then it works fine, I can see the video from the laptop camera.
Am I doing anything wrong? Please help!
public partial class MainWindow : Window
{
WPFMediaKit.DirectShow.Controls.VideoCaptureElement VCE;
public MainWindow()
{
InitializeComponent();
VCE = new WPFMediaKit.DirectShow.Controls.VideoCaptureElement();
Content = VCE;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
VCE.MediaOpened += VCE_MediaOpened;
VCE.MediaFailed += VCE_MediaFailed;
VCE.VideoCaptureDevice = WPFMediaKit.DirectShow.Controls.MultimediaUtil.VideoInputDevices[0]; // This is my laptop webcam
}
void VCE_MediaOpened(Object sender, RoutedEventArgs e) { ... }
void VCE_MediaFailed(object sender, WPFMediaKit.DirectShow.MediaPlayers.MediaFailedEventArgs e) { ... }
}
I had a similar problem with a MediaUriElement working in XAML but not working when instantiated in code-behind.
The solution for me was to Init the control:
VCE.BeginInit();
VCE.EndInit();
This would fit between instantiating (VCE = new...) and assigning (Content = VCE). I haven't tested your particular scenario, but it sounds like the same cause - there must be some extra work done in Init that happens automatically when using XAML.

WPF ListView - How to copy individual cells

I have code where I can take a look at the SelectedItem and then output ToString() to get the record into the clipboard.
How can I detect what cell the user is right clicking on in order to copy just that cell in the SelectedItem?
For example, if I have Borrower Information and the user right-clicks on last name, I would like to give the ability to just copy last name to clipboard.
Thank you!
UPDATE:
Here is the code that I used as suggested by Josh, it worked great:
private void BorrowerInfoCopyClicked(object sender, RoutedEventArgs e)
{
BorrowerViewModel vm = this.DataContext as BorrowerViewModel;
if (vm != null)
{
Clipboard.SetData(DataFormats.Text, vm.CurrentTextBlockText);
}
}
private void AddressCopyClicked(object sender, RoutedEventArgs e)
{
BorrowerViewModel vm = this.DataContext as BorrowerViewModel;
if (vm != null)
{
Clipboard.SetData(DataFormats.Text, vm.CurrentTextBlockText);
}
}
private void lstViews_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
BorrowerViewModel vm = this.DataContext as BorrowerViewModel;
if (vm != null)
{
if (e.OriginalSource is TextBlock)
{
TextBlock txtBlock = e.OriginalSource as TextBlock;
vm.CurrentTextBlockText = txtBlock.Text;
}
}
}
I've done this by handling the PreviewMouseRightButtonDown event on the ListView and checking if e.OriginalSource is a TextBlock. If so, copy the txtBlk.Text to the clipboard. This code could either be in the code-behind of the View that contains the ListView, or as a behavior you attach to the ListView. If you need to use a context menu to perform the Copy operation, have a TextBlock field that you use to store a reference to the TextBlock, and in your method that responds to a MenuItem's click (or Command execution) reference the TextBlock there instead.

Deselecting item from Silverlight datagrid if it's clicked twice

I have a Silverlight 4.0 datagrid, which has the SelectionMode set to Single. The problem with this is that users need to CTRL+Click on an already-selected row in order to deselect it (and have nothing selected in the grid). I'd like for them to be able to simply left-click on the already-selected row to have it deselected.
I tried doing this with a SelectionChanged event (inspecting the added items in the event arguments), however it didn't work because the event isn't thrown when the user clicks on the same row twice.
Any advice?
There is no way to capture the second event because it is never fired. What you could do is apply the type of customization used in this project to one that does capture the second click and fire the event a second time should you wish:
http://www.codeproject.com/KB/silverlight/doubleClickDataGridSL.aspx
I have the same task, so here is my solution:
attach handler for datagrid's MouseLeftButtonDown event using AddHandler dataGrid.AddHandler(UIElement.MouseLeftButtonDownEvent, new MouseButtonEventHandler(DataGrid_MouseLeftButtonDown), true);
, save SelectedIndex in private variable
private int prevSelectedIndex;
void DataGrid_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (prevSelectedIndex != -1 && prevSelectedIndex == dataGrid.SelectedIndex)
{
dataGrid.SelectedIndex = -1;
}
prevSelectedIndex = dataGrid.SelectedIndex;
}
if you want reuse this logic you can create Behavior for DataGrid type
Add System.Windows.Interactivity assembly reference, add class DataGridSecondClickUnselectBehavior
public class DataGridSecondClickUnselectBehavior : Behavior<DataGrid>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.AddHandler(UIElement.MouseLeftButtonDownEvent, new MouseButtonEventHandler(AssociatedObject_MouseLeftButtonDown), true);
}
private int prevSelectedIndex;
void AssociatedObject_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (prevSelectedIndex != -1 && prevSelectedIndex == AssociatedObject.SelectedIndex)
{
AssociatedObject.SelectedIndex = -1;
}
prevSelectedIndex = AssociatedObject.SelectedIndex;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.RemoveHandler(UIElement.MouseLeftButtonDownEvent, new MouseButtonEventHandler(AssociatedObject_MouseLeftButtonDown));
}
}
Now after you compile solution in blend you can add this behavior simply Drag'n'drop from Assets->Behaviors to DataGrid control

Error with calling event inside another event

I am using silverlight, My code is set up for a usercontrol as follows:
myxaml.xaml (Just showing the toggle button [line 119])
<ToggleButton x:Name="btnToggleResizeMap" Checked="btnToggleResizeMap_Checked" Unchecked="btnToggleResizeMap_Unchecked" IsChecked="True"/>
codebehind.cs
public partial class MapRadar : UserControl
{
public delegate void OnMapExpandChange(object sender, EventArgs e);
public event OnMapExpandChange Expanded;
public event OnMapExpandChange NotExpanded;
private void btnToggleResizeMap_Checked(object sender, System.Windows.RoutedEventArgs e)
{
NotExpanded(this, null); //If i remove this line, the app runs fine
}
private void btnToggleResizeMap_Unchecked(object sender, System.Windows.RoutedEventArgs e)
{
Expanded(this, null); //If i remove this line, the app runs fine
}
}
Visual studio throws this error before the application is completely loaded:
AG_E_PARSER_BAD_PROPERTY_VALUE [Line: 119 Position: 285]
at:
System.Windows.Application.LoadComponent(this, new System.Uri("/Xormis.Silverlight.ExSys;component/Views/Map/MapRadar.xaml", System.UriKind.Relative));
which is located inside a function named public void InitializeComponent()
I have no idea what is happening here, is there something against having event calls inside another event?
The problem is that you have null events. As soon as the checkbox is created, it immediately raises the Unchecked event, which calls your btnToggleResizeMap_Unchecked handler, which tries to call your Expanded event. Since Expanded is null, an exception is thrown, and it never finishes running the XAML.
Your code should look like this:
private void btnToggleResizeMap_Checked(object sender, System.Windows.RoutedEventArgs e)
{
if (NotExpanded != null)
NotExpanded(this, null);
}
private void btnToggleResizeMap_Unchecked(object sender, System.Windows.RoutedEventArgs e)
{
if (Expanded != null)
Expanded(this, null);
}
For a more thorough description of events, see C# Events and Thread Safety

Force validation on bound controls from XAML?

There is a very similar question already posted. In fact, the result of the answer in that post is exactly what I'm after, but I have no codebehind to place that code in. All of our logic is encapsulated in a ViewModel. Since the ViewModel is not supposed to have direct references to specific visual elements, this code cannot exist there either. Is there a way to perform this same thing in XAML somehow, or have I finally ran into a reason to be forced to create codebehind files?
You could try doing something with attached properties..it's a bit elaborate, but it does the same as the other answer, so i think it should work:
public class DependencyPropertyCollection : List<DependencyProperty>
{ }
public static class ValidationUtil
{
public static readonly DependencyProperty ForceValidationProperty =
DependencyProperty.RegisterAttached("ForceValidation", typeof(DependencyPropertyCollection), typeof(ValidationUtil), new PropertyMetadata(OnForceValidationChanged));
private static void OnForceValidationChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
element.Loaded += OnElementLoaded;
}
private static void OnElementLoaded(object sender, RoutedEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
element.Loaded -= OnElementLoaded;
foreach (DependencyProperty property in GetForceValidation(element))
element.GetBindingExpression(property).UpdateSource();
}
public static DependencyPropertyCollection GetForceValidation(DependencyObject obj)
{
return (DependencyPropertyCollection)obj.GetValue(ForceValidationProperty);
}
public static void SetForceValidation(DependencyObject obj, DependencyPropertyCollection value)
{
obj.SetValue(ForceValidationProperty, value);
}
}
And you use it like this:
<TextBlock Text="{Binding Text}">
<local:ValidationUtil.ForceValidation>
<local:DependencyPropertyCollection>
<x:StaticExtension Member="TextBlock.TextProperty"/>
</local:DependencyPropertyCollection>
</local:ValidationUtil.ForceValidation>
</TextBlock>
Inside the collection you specify each DependencyProperty which has a binding that you want to validate.

Resources