Win RT Xaml GridView: Drag select multiple items - xaml

I'm trying to select multiple items in a GridView by hovering over them with pressed mouse (like drawing). I tried to achieve this with the PointerEntered event but I'm unable to change the selction from code. Is there a way to implement a custom selection mode?
This didn't work for me because I can't use Style.Triggers in Win RT XAML:
https://stackoverflow.com/a/2886223/5739170

You will have to inherit the gridview control and override the PrepareContainerForItemOverride method:
The code:
public class MyGridView : GridView
{
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
(element as GridViewItem).PointerMoved += MyGridView_PointerMoved;
base.PrepareContainerForItemOverride(element, item);
}
private void MyGridView_PointerMoved(object sender, PointerRoutedEventArgs e)
{
//your logic for setting the isselected
(sender as GridViewItem).IsSelected = true;
}
}

This is how I finally implemented it based on Chirag Shah's answer:
class MyGridView : GridView
{
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
(element as GridViewItem).PointerEntered += SelectItemOnEntered;
(element as GridViewItem).AddHandler(PointerPressedEvent, new PointerEventHandler(SelectItemOnPressed), true);
base.PrepareContainerForItemOverride(element, item);
}
private void SelectItemOnPressed(object sender, PointerRoutedEventArgs e)
{
(sender as GridViewItem).IsSelected = !(sender as GridViewItem).IsSelected;
}
private void SelectItemOnEntered(object sender, PointerRoutedEventArgs e)
{
if (e.Pointer.IsInContact)
(sender as GridViewItem).IsSelected = !(sender as GridViewItem).IsSelected;
}
}
I hope this helps everyone who wants to implement this selection mode.

Related

PRISM Xamarin - Working with tabbed pages (IActiveAware)

I have tab pages implementing different views, but I cannot initialize each of the tabs when navigating.
<TabbedPage.Children>
<tabPages:Page1/>
<tabPages:Page2/>
<tabPages:Page3/>
</TabbedPage.Children>
So what I did was to use IActiveAware as prism documentation suggested to know which tab page is currently active. So I have this class:
public abstract class TabbedChildViewModelBase : BaseViewModel, IActiveAware, INavigationAware, IDestructible
protected bool IsInitalized { get; set; }
private bool _IsActive;
public bool IsActive
{
get
{
return _IsActive;
}
set
{
SetProperty(ref _IsActive, value, RaiseIsActiveChanged);
}
}
public event EventHandler IsActiveChanged;
public virtual void OnNavigatingTo(NavigationParameters parameters)
{
}
protected virtual void RaiseIsActiveChanged()
{
IsActiveChanged?.Invoke(this, EventArgs.Empty);
}
public virtual void Destroy()
{
}
}
So each child view models inherits the child view model base:
public class Page1 : TabbedChildViewModelBase
{
public CurrentSeaServiceViewModel()
{
IsActiveChanged += HandleIsActiveTrue;
IsActiveChanged += HandleIsActiveFalse;
}
private void HandleIsActiveTrue(object sender, EventArgs args)
{
if (IsActive == false)
{
TestLabelOnly = "Test";
}
// Handle Logic Here
}
private void HandleIsActiveFalse(object sender, EventArgs args)
{
if (IsActive == true) return;
// Handle Logic Here
}
public override void Destroy()
{
IsActiveChanged -= HandleIsActiveTrue;
IsActiveChanged -= HandleIsActiveFalse;
}
}
The problem is, the child vm isn't initializing. Is there something needed in order to implement IActiveAware properly nor launching the IsActive property
I still used IActiveAware unfortunately, to make the childtabbedviewmodel work you need to bind the page to its own view model.
So here's what I did:
<TabbedPage.Children>
<views:ChildPage1>
<views:ChildPage1.BindingContext>
<viewModels:ChildPage1ViewModel/>
</views:ChildPage1.BindingContext>
</views:ChildPage1>
<views:ChildPage2>
<views:ChildPage2.BindingContext>
<viewModels:ChildPage2ViewModel/>
</views:ChildPage2.BindingContext>
</views:ChildPage2>
</TabbedPage.Children>
I used the property BindingContext of my views and
using IActiveAware I would also know what tab is currently active. Hope anyone helps this who finds trouble binding the child pages of a tab.

How to use Xamarin Forms Custom Button Renderer's Touch event to change the Buttons Image

I figured it out.
For anyone needing this. Please see the following.
After Watching Xamarin Evolve a million times I caught on.
class LoginButtonCustomRenderer : ButtonRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
{
base.OnElementChanged(e);
Android.Widget.Button thisButton = Control as Android.Widget.Button;
thisButton.Touch += (object sender, TouchEventArgs e2) =>
{
if (e2.Event.Action == MotionEventActions.Down)
{
System.Diagnostics.Debug.WriteLine("TouchDownEvent");
// Had to use the e.NewElement
e.NewElement.Image = "pressed.png";
}
else if (e2.Event.Action == MotionEventActions.Up)
{
System.Diagnostics.Debug.WriteLine("TouchUpEvent");
}
};
}
}
you need call
Control.CallOnClick();
Here is a sample how to implement a two state ImageButton in Xamarin Forms:
PCL:
public class FancyButton : Button
{
public void SendClickedCommand()
{
ICommand command = this.Command;
if (command != null)
{
command.Execute(this.CommandParameter);
}
}
}
Android render:
public class FancyButtonAndroid : ButtonRenderer
{
Android.Widget.Button thisButton;
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
{
base.OnElementChanged(e);
thisButton = Control as Android.Widget.Button;
thisButton.SetBackgroundResource(Resource.Drawable.btn_unpress);
thisButton.Touch += ThisButton_Touch;
thisButton.Click += HandleButtonClicked;
}
private void ThisButton_Touch(object sender, TouchEventArgs e)
{
e.Handled = false;
if (e.Event.Action == MotionEventActions.Down)
{
System.Diagnostics.Debug.WriteLine("TouchDownEvent");
thisButton.SetBackgroundResource(Resource.Drawable.btn_press);
}
else if (e.Event.Action == MotionEventActions.Up)
{
System.Diagnostics.Debug.WriteLine("TouchUpEvent");
thisButton.SetBackgroundResource(Resource.Drawable.btn_unpress);
}
}
private void HandleButtonClicked(object sender, EventArgs e)
{
if (Element != null && Element is FancyButton)
{
(Element as FancyButton).SendClickedCommand();
}
}
protected override void Dispose(bool disposing)
{
if (thisButton != null)
{
thisButton.Touch -= ThisButton_Touch;
thisButton.Click -= HandleButtonClicked;
}
base.Dispose(disposing);
}
}
Note: in the Touch event set: e.Handled = false; to cause the Click event to rise.

WP8 LongListSelector SelectedItem not bindable

In WP8, they forgot to provide SelectedItem as a dependency property, hence I'm not able to bind to it. I fixed that using this: http://dotnet-redzone.blogspot.com/2012/11/windows-phone-8longlistselector.html
On doing so, I'm noticing that I'm not able to reset the property from the ViewModel, i.e. if I set the item to null in the ViewModel, it does not impact the UI. I have already provided two way binding in the UI but still setting the item to null in the ViewModel does not change the selected item in the LongListSelector. I also don't want to use the SelectionChanged event as I'm sharing ViewModels between WP7.5 app and a WP8 app, hence I want to push as much as I can into the ViewModel. Is there a solution for this?
It appears that the custom LongListSelector class that you are using does not handle the setter properly.
Replace the OnSelectedItemChanged callback with the following:
private static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var selector = (LongListSelector)d;
selector.SetSelectedItem(e);
}
private void SetSelectedItem(DependencyPropertyChangedEventArgs e)
{
base.SelectedItem = e.NewValue;
}
And there is full version of these two parts:
public class LongListSelector : Microsoft.Phone.Controls.LongListSelector
{
public LongListSelector()
{
SelectionChanged += LongListSelector_SelectionChanged;
}
void LongListSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
SelectedItem = base.SelectedItem;
}
public static readonly DependencyProperty SelectedItemProperty =
DependencyProperty.Register(
"SelectedItem",
typeof(object),
typeof(LongListSelector),
new PropertyMetadata(null, OnSelectedItemChanged)
);
private static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var selector = (LongListSelector)d;
selector.SetSelectedItem(e);
}
private void SetSelectedItem(DependencyPropertyChangedEventArgs e)
{
base.SelectedItem = e.NewValue;
}
public new object SelectedItem
{
get { return GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
}

Extend DropDownList to add ListSearchExtender

I want to extend DropDownList to add ListSearchExtender.
Using the code below, the control works well in runtime but in design time it give me this error:
SearchDropDownList - DdlTest There was an error rendering the
control. Page cannot be null. Please ensure that this operation is
being performed in the context of an ASP.NET request.
I'd like to understand the cause of this error.
[ToolboxData("<{0}:SearchDropDownList runat=\"server\"></{0}:SearchDropDownList>")]
public class SearchDropDownList : DropDownList
{
private ListSearchExtender listSearchExt = new ListSearchExtender();
protected override void OnInit(EventArgs e)
{
ReloadSettings();
}
protected override void Render(HtmlTextWriter w)
{
base.Render(w);
listSearchExt.RenderControl(w);
}
public void ReloadSettings()
{
listSearchExt.TargetControlID = this.ID;
listSearchExt.ID = this.ID + "_CalendarExtender";
if (Controls.Count > 0)
{
foreach (Control item in Controls)
{
if (item.ID == listSearchExt.ID)
{
Controls.Remove(item);
}
}
}
Controls.Add(listSearchExt);
}
}
i got it by simple way i am not sure if it will make problem in future but for now it work well
protected override void Render(HtmlTextWriter w)
{
base.Render(w);
if (!this.DesignMode)
{
listSearchExt.RenderControl(w);
}
}

Why Won't the Silverlight ChildWindow Display?

I have a simple Silverlight 4 application and have added a child window to it. I am using the below code to open it on a button click. This seems like it should work, does it not?
public void btnAbout_Click(object sender, RoutedEventArgs e)
{
About aboutThis = new About();
aboutThis.Show();
}
The "About" class looks like this:
public partial class About : ChildWindow
{
public About()
{
InitializeComponent();
}
private void OKButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
}
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = false;
}
}
I don't see any reason why it should not work.
Samples:
http://www.tanguay.info/web/index.php?pg=codeExamples&id=135
http://www.silverlighttoys.com/Tutorials.aspx?tutorial=2
What is your XAML like?
Try setting the Width and Height to 600px by 600px of your About Childwindow from xaml.