Make UserControl "slide out" from a side of a screen? - c#

I'm using following code to inject view into Grid:
private void OnShowNotesRequested(UserControl view)
{
if (view == null) throw new NotSupportedException("View should not be null");
// Skip first GridRow - this is usually Toolbar
if (this.AssociatedObject.RowDefinitions.Count > 1)
{
view.SetValue(Grid.RowSpanProperty, this.AssociatedObject.RowDefinitions.Count - 1);
view.SetValue(Grid.RowProperty, 1);
}
view.SetValue(Grid.ColumnSpanProperty, this.AssociatedObject.ColumnDefinitions.Count == 0 ? 1 : this.AssociatedObject.ColumnDefinitions.Count);
view.Width = 500;
view.HorizontalAlignment = HorizontalAlignment.Right;
this.AssociatedObject.Children.Add(view);
}
Basically, I'm adding view as a child to the Grid. It docks to the right side.
I want to make it look like this view sliding out of right side and stops. I have no idea on how to approach it and what should I do to achieve this visual effect. Any pointers on what and where I need to add? Maybe link to similar effect?
I found some animations code here: http://forums.silverlight.net/t/82441.aspx
It makes sense, however when I hide my view - I completely remove it from visual tree like so: this.AssociatedObject.Children.Remove(view) Not sure how to "wait" and then remove it.

Take a look at Microsofts Expression Blend tool, its been created specifically to create these kind of visual effects.
What you are looking to do can be acheived with a story board and is pretty simple to do!
Essentially, once the storyboard has been created (a case of defining the starting position and the end position - according to time (or frames)) you can trigger the storyboard to play when a particular event is fired.
I know this is not a definitive answer however here are some tutorials to get you moving:
http://www.silverlightbuzz.com/2009/10/12/animating-with-storyboards-in-blend/
http://www.c-sharpcorner.com/uploadfile/mamta_m/creating-and-using-storyboards-in-blendsilverlight-part-i/
http://www.google.co.uk/url?sa=t&rct=j&q=&esrc=s&source=web&cd=4&ved=0CE4QFjAD&url=http%3A%2F%2Fmsdn.microsoft.com%2Fen-us%2Flibrary%2Fcc295092.aspx&ei=NDRzT42uPNS_8gPrz6xW&usg=AFQjCNGwT_hEkwGBXzS3holaM1g85I0S5Q&sig2=dSDJ6lL0CR3-nIR7WQ739g
Thanks and good luck!
Ben

Related

C# WPF - Custom Control drag and drop (Visual Studio style)

How do I make my Custom controls draggable and droppable on a grid let's say?
I want to drag a panel(custom control) and drop it somewhere on my screen, in the best case in a grid, for example how it's done in Visual Studio, you can grab the solution explorer let's say and drop it somewhere, but how exactly do I do that?
You need to build your project and then it will be automatically available in the Toolbox when you are in the XAML designer. Just like the common controls.
For Drag and Drop at runtime look and the official WPF documentation. Also I suggest you look at the GongSolutions.WPF.DragDrop library in GitHub it is open source so you can see how they implemented it if the functionality it provides does not do what you want.
I found this post with a very similar conclusion to this one. the difference being scale.
the following example will swap the parent container
int i = 0;
void swapLocations()
{
foreach(var formObject in objList) //objList == a list or array on all objects you want to move from one container to another
{
if (i % 2 == 0)
{
// catch current position
Point moveLocation = new Point(formObject.Location.X + formObject.Parent.Location.X,formObject.Location.Y + formObject.Parent.Location.Y);
// remove this object
formObject.Parent.Controls.Remove(formObject);
// add this object to the form
this.Controls.Add(formObject);
// set location
formObject.Location = moveLocation;
formObject.SendToBack();
}
else
{
formObject.BringToFront();
}
}
++i;
}

LayoutParams change only takes effect in fullscreen

im using Xamarin with MvvmCross.
Ive done a FragmentDialog with a recyclerView inside, the list is populated via bindings on xml file, so i have no adapter and i should keep it this way.
If im not wrong, theres no built in way to make the recyclerView take only the size needed for its content, this should not be a problem, but in this case i need the list to start from bottom...
So i did this (its a custom fullscreen dialog) :
MvxRecyclerView list = Dialog.FindViewById<MvxRecyclerView>(Resource.Id.recyclerview);
list.LayoutChange += List_LayoutChange;
Then in layoutChange
private void List_LayoutChange(object sender, View.LayoutChangeEventArgs e)
{
MvxRecyclerView list = Dialog.FindViewById<MvxRecyclerView>(Resource.Id.recyclerview);
int itemHeight = list.GetChildAt(0).Height;
if (itemHeight != 0)
{
ViewGroup.LayoutParams prms = list.LayoutParameters;
prms.Height = itemHeight * list.GetAdapter().ItemCount;
list.LayoutParameters = prms;
list.LayoutChange -= List_LayoutChange;
list.RequestLayout();
}
}
That was working fine, the list get exactly the height needed and the list looks like it starts from bottom.
Now the client tell me that he doesnt like the fullscreen dialog and wants the status bar, i think that should be easy, just to remove this line at the dialog creation right?
dialog.Window.AddFlags(WindowManagerFlags.Fullscreen);
But looks like its not that easy, when the dialog its not fullscreen the layoutParams change seems to have no effect, it just dont do nothing.
My method is being called and i get the right item height, it just dont change the recyclerview height.
Notice that setting fullscreen at creation and clearing the flag after the recyclerview params change works
So looks like it only works during fullscreen mode.
Can someone throw some light at this?
Thanks in advance.
As you said, RecyclerView was not aware of its size.
Since last update to the support lib, it is !
http://android-developers.blogspot.fr/2016/02/android-support-library-232.html
The RecyclerView widget provides an advanced and flexible base for creating lists and grids as well as supporting animations. This release brings an exciting new feature to the LayoutManager API: auto-measurement! This allows a RecyclerView to size itself based on the size of its contents. This means that previously unavailable scenarios, such as using WRAP_CONTENT for a dimension of the RecyclerView, are now possible. You’ll find all built in LayoutManagers now support auto-measurement.
I would suggest to wait for the Xamarin wrapped lib (there is already a beta https://www.nuget.org/packages/Xamarin.Android.Support.v4/23.2.0-beta1)

Button Questions in MonoTouch

I'm working with MonoTouch and I have come up with three questions around buttons that I'm hoping someone can help me with.
I'm trying to change the "Back" button in the title bar. How do I do this? I've seen the thread posted here: How to change text on a back button. However, that doesn't work. I get the vibe that I'm not accessing the controller property. Currently, I receive a NullReferenceException when I attempt to set the button text in the ViewDidLoad method. Currently, I'm trying to set the text like such:
this.NavigationItem.BackBarButtonItem.Title = "Back";
I have the suspicion that I'm not accessing the root controller, but I'm not sure how to do this.
For a "back" button on a separate page, I want to perform a custom action. I want it to go back like it does. But before that happens, I want to execute some custom code. How do I do this?
I need to create something that looks like a hyperlink within a paragraph of text. How do I do that?
MonoTouch seems cool. However, the learning curve is a bit steeper than I had anticipated. Thank you!
For your first question the MonoTouch-specific answer (to the question you provided) works perfectly.
this.NavigationItem.BackBarButtonItem = new UIBarButtonItem ("MyBack", UIBarButtonItemStyle.Plain, null);
Make sure to the all the answers. This code needs to be called in the pushing controller, not the controller being pushed.
UPDATE
For your second question you likely noticed a few overloads that takes a Selector or a delegate. However they won't work for a Back button.
One way to work around this iOS limitation is to override ViewDidAppear or ViewDidDisappear to get similar notification.
I solved your third question by creating a custom button in de viewbuilder. Setting the type to custom removes de standard borders and makes it look like a line of text. Simply change its size and style it to make it look more like an hyperlink. I left an empty space in my text and and put my custom button in that space.
I created an extension method that allows you to change the back button text and optionally handle the TouchUp action with your own code. It also keeps the same border look as the default back button.
public static class MyExtensions
{
public static void SetCustomBackButton(this UIViewController uiViewController, string buttonText, Action onClick)
{
uiViewController.NavigationItem.HidesBackButton = true;
var dummyButton = UIButton.FromType (UIButtonType.Custom);
var backButton = (UIButton)MonoTouch.ObjCRuntime.Runtime.GetNSObject (
MonoTouch.ObjCRuntime.Messaging.IntPtr_objc_msgSend_int (
dummyButton.ClassHandle, MonoTouch.ObjCRuntime.Selector.GetHandle ("buttonWithType:"), 101));
backButton.SetTitle (buttonText, UIControlState.Normal);
backButton.TouchUpInside += delegate {
if (onClick != null)
onClick ();
else
uiViewController.NavigationController.PopViewControllerAnimated (true);
};
uiViewController.NavigationItem.LeftBarButtonItem = new UIBarButtonItem (backButton);
}
}

Design-Time drag and drop

I'm currently working of a project where my part is to design a Design Surface where the end user can add/remove/move controls at run-time.
I followed this tutorial "Hosting Windows Forms Designers, by Tim Dawson", and almost have implemented all the features I need.
Short story for those who don't want to read the tutorial : I implemented IDesignerHost, IContainer, ISelectionService, IToolboxService and some other interface, to create my design surface. I didn't use the System.ComponentModel.Design.DesignSurface already in the framework, mainly beacause I need a really custom design surface.
Question :
I want to allow user to drag & drop new Control from the IToolboxService to the IDesignerHost/IContainer. In this tutorial, you clic on a Control in the toolbox, the click on the design surface to add the control.
What i've found :
There is a built-in feature that
automagically does drag & drop from
IToolboxService to
System.ComponentModel.Design.DesignSurface but it is clearly not working if you implement IDesignerHost from nothing.
When you use the
Control.DoDragDrop(ToolboxItem)
method, to initiate a drag & drop :
IToolboxService.SerializeToolboxItem(ToolboxItem)
is called to serialize the item
IToolboxService.IsToolboxItem(object)
and
IToolboxService.IsSupported(object)
are called to evaluate if the
serialized ToolboxItem can be allowed
to be droped on the design surface
When you drop the control : IToolboxService.DeserializeToolboxItem(object serializedObject) is called by the design surface to deserialize the controldropped.
IToolboxService.SetCursor() is called to know if you define a custom cursor, or let the standard windows cursor.
Problem :
I implemented all mentionned above, in the "What i've found", but the drag & drop is buggy :
I drag, everything's fine, but when
hovering the design surface, my
cursor blink a little between
standard cursor and the
"DragDropEffects.Copy" style.
When I drop, nothing happens, and when my cursor leave the design surface (after I dropped), then the new Control is created and added where I dropped it.
Has anyone ever tried to do what I'm doing, and if so, how did you manage it ?
Is there anyone that has any pointer/link/good advices ?
Thank you =)
Is there anyone that has any
pointer/link/good advices?
Your issue seems to be addressed by the Microsoft Connect issue Mouse Events Consumed / Not Raised in 2.0 Designers. This issue is all but easy to grasp though, but apparently the upgrade from .NET Framework 1.1 (2003) to 2.0 (2006) implied a change in drag & drop behavior - given that the article you mentioned stems from 2003 this could well be related. Specifically you should scroll ahead to section Issue 2, citation:
You will now notice constant
flickering when dragging over the
form. This is partially caused by the
new drag-drop behavior in 2.0.
I'm unable to dig deeper into this right now myself but you might also be able to figure something from Customize Drag & Drop in the Designer, which addresses changed behavior regarding drag & drop between Visual Studio versions 2003 and 2005; quite likely this might be related and one of the accepted answers does in fact specifically reference the Microsoft Connect issue above, plus it offers more hints towards possible solutions too.
Me to worked on this questions for one day ago. This is my solution that found for my project like yours.
I drag, everything's fine, but when hovering the design surface, my cursor blink a little between standard cursor and the "DragDropEffects.Copy" style.
This is my toolboxservice.
class EasyAccordionToolboxService : AccordionControl, IToolboxService
{
EasyAccordionControlElement _SelectedElement;
public Control DesignPanel { get; set; }
public EasyAccordionToolboxService()
{
AddAccordions();
AllowItemSelection = true;
base.ElementClick += EasyAccordionToolboxService_ElementClick;
}
private void EasyAccordionToolboxService_ElementClick(object sender, ElementClickEventArgs e)
{
if (e.Element.Level == 1) this._SelectedElement = e.Element as EasyAccordionControlElement;
}
public ToolboxItem GetSelectedToolboxItem()
{
if(_SelectedElement != null)
{
var selectedToolboxItem = this._SelectedElement.ToolBoxItem;
this._SelectedElement = null;
return selectedToolboxItem;
}
else
{
return null;
}
}
public bool SetCursor()
{
if(this._SelectedElement == null)
{
this.DesignPanel.Cursor = Cursors.Default;
}
else
{
this.DesignPanel.Cursor = Cursors.Hand;
}
return true;
}
There are "DesignPanel" property and "SetCursor" methods. DesignPanel property is control referred to view of root designer.
When I drop, nothing happens, and when my cursor leave the design surface (after I dropped), then the new Control is created and added where I dropped it.
There is GetSelectedToolboxItem method in EasyAccordionToolBoxService implemented from IToolboxService. GetSelectedToolboxItem is your answer.
Finally,
designer = new EasyDesignSurface(propertyGrid);
var rootForm = (Form)designer.CreateComponent(typeof(Form));
rootForm.Name = "rootForm";
rootForm.Text = "BELGE";
rootForm.TopLevel = false;
rootForm.Size = new Size(600, 600);
designer.ComponentContainer.Add(rootForm);
var view = (Control)designer.View;
view.Dock = DockStyle.Fill;
designPanel.Controls.Add(view);
easyAccordionToolboxService1.DesignPanel = view;
designer.AddService(typeof(IToolboxService), easyAccordionToolboxService1);

How to Find Children of a UserControl instead of a Window - replacing Window.FindName

I currently have a WPF project which has one main Window, and many UserControls which are children of this Window. Many of the children of this window are Tabs. I have successfully replaced my main Window with a User Control that implements almost exactly the same functionality as the Main Window.
Replacing the Window with a UserControl introduced one problem - currently our application determines which programming tab to display based on the parent window by using the Window.FindName method shown below. Therefore I need to replace the Application.Current.MainWindow with an appropriate description of my main user control. See the erroring C# method below and wpf instantiation of the tabs for clarification.
Note Regarding Window.FindName() method - the reason why it does not work after I replaced it with a UserControl is because the FindName method searches upwards in the visual tree, as described here.
Does anyone know how to find a user control based on the x:Name, similar to Application.Current.MainWindow ? Also, is there a better way to find the UserControl than looking for the x:Name string in case it gets renamed?
How we currently find the MainWindow - need to now find MainUserControl:
(C#)
private static void SetCurrentProgram(int num)
{
Window window = Application.Current.MainWindow;
ProgrammingTab programmingTab1 = window.FindName("ProgrammingTab1") as ProgrammingTab;
ProgrammingTab programmingTab2 = window.FindName("ProgrammingTab2") as ProgrammingTab;
programmingTab1.Visibility = num == 1 ? Visibility.Visible : Visibility.Collapsed;
programmingTab2.Visibility = num == 2 ? Visibility.Visible : Visibility.Collapsed;
}
Instantiation of programming tabs.
(xaml)
<Grid>
<ProgrammingControl:ProgrammingTab x:Name="ProgrammingTab1" Program="1" IsVisibleChanged="ProgrammingTab_IsVisibleChanged" />
<ProgrammingControl:ProgrammingTab x:Name="ProgrammingTab2" Program="2" IsVisibleChanged="ProgrammingTab_IsVisibleChanged" />
</Grid>
It sounds like your app is developed in a very WinForms-like style. To stick with that style and simply answer your question, you can FindName() to find the UserControl and again to find the ProgrammingTab, like this:
var userControl = (MyUserControl)Application.Current.MainWindow.FindName("userControlName");
var programmingTab1 = (ProgrammingTab)userControl.FindName("ProgrammingTab1");
var programmingTab2 = (ProgrammingTab)userControl.FindName("ProgrammingTab2");
...
However I would recommend you look into using WPF's advanced capabilities such as data binding. You can have a DependencyProperty "CurrentProgram" on a singleton object referenced by a static property, and simply databind Visiblity to it using a converter.
<ProgrammingTab Visibilty="{Binding CurrentProgram,
Source={x:Static MyState.Instance},
Converter={x:Static VisibleIfEqualConverter},
ConverterParameter=1}" ...>
...
With this change, your SetCurrentProgram becomes simply:
public void SetCurrentProgram(int num)
{
MyState.Instance.CurrentProgram = num;
}
The beauty of this technique is that any ProgrammingTab anywhere in your application will automatically appear or disappear every time MyState.Instance.CurrentProgram's vaulue changes, with no need to find them with FindName() or otherwise.
I figured out a workaround to this problem: I created a new algorithm based on another StackOverflow user's algorithm that recursively found any children of a DependencyObject. Find my solution here. If you declare the FindChild() method in my other post within public static class UIHelper {} you can then solve the problem by doing this:
ProgrammingTab programmingTab1 = UIHelper.FindChild<ProgrammingTab>(Application.Current.MainWindow, "ProgrammingTab1");
ProgrammingTab programmingTab2 = UIHelper.FindChild<ProgrammingTab>(Application.Current.MainWindow, "ProgrammingTab2");
This still uses procedural code instead of declarative XAML for bindings like RayBurns suggested. If it works, his solution will be much more efficient as it wont be traversing a whole tree but rather just changing the visibility of tabs based on a converter. I'll test that solution now and see how it turns out.
The reason why FindName() doesn't work properly is described in the post here.
This article may helps you : http://blog.lexique-du-net.com/index.php?post/2010/09/14/UserControl/Control-how-to-get-a-reference-to-an-element-of-the-template

Categories