How to bind to observable collection in code-behind from xaml - observablecollection

Hi how can i bind to this observablecollection
(Mainpage.xaml.cs)
public ObservableCollection tabs = new ObservableCollection();
in xaml? I've tried
(Mainpage.xaml)
But without any luck

a common pattern would be to set a DataContext in you loaded event, assuming you want to bind it to a TabControl called tabs_control on your page:
public MainPage()
{
InitializeComponent();
Loaded += OnLoaded;
}
protected void OnLoaded(object sender, RoutedEventArgs e)
{
//Initialize tabs collection
tab_control.ItemsSource = tabs;
}
Obviously you should substitute the actually control you want to bind to.
EDIT
Base on your comments, what you could do is just setup the control to be the data context, then your XAML binding should work. so instead of above you would do this:
protected void OnLoaded(obejct sender, RoutedEventArgs e)
{
this.DataContext = this;
}
then in your XAMl you could do this:
<TabControl ItemsSource={Binding tabs} ... />

Use WPF's binding syntax for XAML.
<YourControl ItemSource="{Binding tabs} />
You also need to set the DataContext of the top level control (grid, canvas etc) to be a type that owns the tabs collection (that type in the case you didn't rename your window's class, would be Window1.
So, for example, combining that with the XAML fragment above:
<Grid DataContext="Window1">
....
....
<YourControl ItemSource="{Binding tabs} />
....
....
</Grid>

Related

Overlay toolbar with other toolbar when item is selected in RecyclerView which is inside a fragment

To illustrate what I mean with this, it is similar to WhatsApp, where various options are displayed in the toolbar when a chat is selected.
I have a similar layout, so a MainActivity with Fragments containing RecyclerViews. Now when an item in a RecyclerView is selected I would like to get a similar behaviour as in WhatsApp. The RecyclerViews have an Adapter that implements an OnClickListener.
However, from this Adapter I do not seem to have access to Views from the MainActivity. I tried the following (inside the OnClick method in the Adapter), but it did not work since the view could not be found.
View view = getActivity().findViewById(R.id.toolbar_main_activity);
if( view instanceof Toolbar) {
Toolbar toolbar = (Toolbar) view;
toolbar.setTitle("TestTitle");
}
Does anyone know how to get the intended behavior or have a reference to a tutorial?
UPDATE: for who is also stuck with this and this is still quite confusing, here is how I solved it in my own words
My Fragment contains the Interface by adding the following code to it;
OnItemsSelected mCallBack;
public interface OnItemsSelected {
void onToolbarOptions(String title);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
mCallback = (OnItemsSelected) getActivity();
}
Also I passed 'mCallback' to the adapter like this;
MyAdapter adapter = new MyAdapter(myList, mCallback);
The RecyclerView adapter implements OnClickListener. In the OnClick method I called; 'mCallBack.onToolbarOptions("someTitle");'. And finally I made my MainActivity implement the method; 'implements myFragment.onItemsSelected' and I added the following code to it also;
#Override
public void onToolbarOptions(String title) {
toolbar.setTitle(title);
}
With this, only the title is changed, but from this it is quite easy to make other changes to the toolbar, such as changing the menu items.
Inside your Fragment you make an Interface and a global variable like this:
OnItemsSelected mCallBack;
public interface OnItemsSelected {
public void onToolbarOptions();
}
Then when in your RecyclerView items are selected or clicked you call:
mCallBack.onToolbarOptions();
In your Activity implement the Interface like this plus the method onToolbarOptions():
public static class YourActivityName extends AppCompatActivity
implements YourFragmentName.OnItemsSelected {
public void onToolbarOptions(){
// CHANGE YOUR TOOLBAR HERE
}
//.....OTHER STUFFS IN YOUR ACTIVITY
}

How can I override or act on KeyDown: Space or Enter for ListView in UWP?

I've attached the KeyDown event to a ListView in my Win 10 UWP app. I want to make VirtualKey.Enter have a special effect, but the event is not firing for this particular key. Neither does it for Space, Arrow up or down. This I guess because the listview already has defined a special behaviour for those keys.
I'd like to override some of those keys though, or at least trigger additional actions. Even attaching events to those key with modifiers (e.g. Shift+ArrowDown) would not work because the events still are not firing.
I read that for WPF that there is a PreviewKeyDown-event which one can attach to. I can't find that event for UWP though. Are there any other options?
Stephanie's answer is a good one and it works in the general case. However, as Nilzor observed it will not work in the case of a ListView for the Enter key. For some reason the ListView handles the KeyDown event in case Enter is pressed.
A better way to handle key events when dealing with a ListView, as the question asks, is this.
private void ListView_Loaded(object sender, RoutedEventArgs e)
{
(sender as ListView).AddHandler(UIElement.KeyDownEvent, new KeyEventHandler(ListView_KeyDown), true);
}
private void ListView_KeyDown(object sender, KeyRoutedEventArgs args)
{
if (args.Key == Windows.System.VirtualKey.Enter)
{
}
}
Notice the last argument in the AddHandler function. This specifies whether we want to handle events already handled by a previous element in the visual tree.
Of course don't forget to unsubscribe from the event when appropriate
Here is one way to do it : subscribe to the global Window.Current.CoreWindow.KeyDown event.
Then save the focus state of your listview and react accordingly.
Here is the code :
public sealed partial class MainPage : Page
{
bool hasFocus = false;
public MainPage()
{
this.InitializeComponent();
Window.Current.CoreWindow.KeyDown += CoreWindow_KeyDown;
}
private void CoreWindow_KeyDown(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.KeyEventArgs args)
{
if(hasFocus)
{
Debug.Write("Key down on list");
}
}
private void myList_GotFocus(object sender, RoutedEventArgs e)
{
hasFocus = true;
}
private void myList_LostFocus(object sender, RoutedEventArgs e)
{
hasFocus = false;
}
You will also need to subscribe to the focus events in xaml, for your ListView :
<ListView .... GotFocus="myList_GotFocus" LostFocus="myList_LostFocus"/>
Corcus's solution doesn't work for me. What is working is handling PreviewKeyDown directly from XAML. Works well for SPACE or ENTER key:
XAML:
<ListView PreviewKeyDown="BookmarksListView_PreviewKeyDown">
Code behind:
private void BookmarksListView_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Enter)
{
// DO YOUR STUFF...
e.Handled = true;
}
}
You can use AddHandler method.
private void KeyEnterEventHandler(object sender, KeyRoutedEventArgs e)
{
if (e.OriginalKey == Windows.System.VirtualKey.Enter)
{
PlayFromListView();
}
}
private void LoadListView()
{
foreach (var music in playListStorageFile.PlayList)
{
ListViewItem item = new ListViewItem();
item.AddHandler(FrameworkElement.KeyDownEvent, new KeyEventHandler(KeyEnterEventHandler), true);
TextBlock mytext = new TextBlock();
mytext.Text = music.Nro.ToString() + " - " + music.Name;
mytext.Tag = music.Nro;
item.Content = mytext;
lvMusics.Items.Add(item);
}
}
https://learn.microsoft.com/en-us/uwp/api/windows.ui.xaml.uielement.addhandler?view=winrt-18362

Edge manipulation detection in fullscreen mode is not working as expected in UWP app

I have a situation where manipulation events emanating from offscreen (think bezel of surface pro) are not being registered when the app is in fullscreen mode. However, they are registering as expected when the application is "maximized" (I put that in quotes because I know it's no longer officially a "thing" to be maximized).
To reproduce, create the blank application and add the code at the end of this post.
Swipe from top down, and notice an absence of any manipulation events being fired. Now click the exit full screen button then the maximize button and repeat the experiment, and you will see that manipulation events now properly fire.
It is important to start dragging offscreen.
Is this by design? Is there a gotcha that I'm not aware of? Is it a bug?
The following Xaml file:
<Page
x:Class="EdgeSwipeDetect.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:EdgeSwipeDetect"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="Green"
ManipulationMode="TranslateInertia,TranslateY"
ManipulationStarted="Grid_ManipulationStarted"
ManipulationCompleted="Grid_ManipulationCompleted"
ManipulationDelta="Grid_ManipulationDelta" />
</Page>
Code behind:
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
CoreApplicationViewTitleBar coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
coreTitleBar.ExtendViewIntoTitleBar = true;
var appView = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView();
appView.TryEnterFullScreenMode();
}
private void Grid_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
{
Debug.WriteLine("ManipulationStarted");
}
private void Grid_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
Debug.WriteLine("ManipulationCompleted");
}
private void Grid_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
Debug.WriteLine("ManipulationDelta");
}
}

MvvmCross and UIButton.Selected UISegmentedControl Bindings, iOS

In a cross platform Xamarin app built with the MvvmCross framework I'm using a ToggleButton Widget in an Android .axml layout. I've bound the Checked property to a View Model property using a converter using the following binding syntax:
Checked MarketBuySellViewModel.Direction, Converter=DirectionBool, ConverterParameter='Sell'
Everything works well. On the iOS side, it appears you can use UIButton as a ToggleButton by using the Selected property. This implies that the following binding should achieve what I want on iOS:
set.Bind (SellButton).For(b => b.Selected).To (vm => vm.MarketBuySellViewModel.Direction).WithConversion("DirectionBool", "Sell");
I don't get any binding errors in the application output but the binding itself doesn't seem to work. Clicking the button doesn't set the Direction property and setting the direction to a different value does not set the Selected property on the UIButton.
Do I need to create a Custom Binding or am I simply setting up the binding incorrectly?
I also tried using a UISegmentedControl to achieve the same effect. Is binding to this control supported at all in MvvmCross? I don't see any reference to it in the source code. Does this mean I need to create custom bindings for it too?
For the UIButton, I don't believe there's any included Selected binding built into MvvmCross. Because of this - and because Selected doesn't have a simple paired event SelectedChanged, then I believe Selected binding should work one-way (from ViewModel to View) but not two-way.
There is a binding for the On of a UISwitch control and that's the control I've seen used most in these situations.
If you wanted to add a custom 2-way binding for Selected then I guess you'd have to do this using the ValueChanged event (but would need to check that is correct).
To do so, you'd just build a target binding something like:
public class MvxUIButtonSelectedTargetBinding : MvxPropertyInfoTargetBinding<UIButton>
{
public MvxUIButtonSelectedTargetBinding(object target, PropertyInfo targetPropertyInfo)
: base(target, targetPropertyInfo)
{
var view = View;
view.ValueChanged += HandleValueChanged;
}
private void HandleValueChanged(object sender, System.EventArgs e)
{
var view = View;
if (view == null)
return;
FireValueChanged(view.Selected);
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.TwoWay; }
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (isDisposing)
{
var view = View;
if (view != null)
{
view.ValueChanged -= HandleValueChanged;
}
}
}
}
and this could be registered in Setup in protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry) using something like:
registry.RegisterPropertyInfoBindingFactory(typeof(MvxUIButtonSelectedTargetBinding), typeof(UIButton),
"Selected");
Similarly, I don't believe anyone has added a two way UISegmentedControl binding yet - but would happily see one added.
Building a two way UISegmentedControl binding would be quite straight-forward - you'd just have to bind to the pair SelectedSegment and ValueChanged - with code similar to above.
Alternatively, you could switch to using a custom MySegmentedControl which had a nicer Value`ValueChanged` pair which would automatically work without a custom binding - e.g.:
public class MySegmentedControl : UISegmentedControl
{
// add more constructors if required
public int Value
{
get { return base.SelectedSegment; }
set { base.SelectedSegment = value; }
}
}
If any or all of these custom bindings are needed, then the Mvx project is happy to get these bindings added as issues or pull requests along with test/demo UIs in the https://github.com/slodge/MvvmCross-Tutorials/blob/master/ApiExamples/ApiExamples.Touch/Views/FirstView.cs project
Could be helpful to someone else, so i'm sharing my experience. I needed a two way binding for UISegmentedControl.SelectedSegment property to a ViewModel. The one way biding (ViewModel => View) works by default. I couldn't able to properly utilize the solution proposed by Stuart - to subclass the UISegmentedControl. I tried to ensure that the linker does not rip off the new custom control code, but this didn't help me a bit. So a perfectly viable solution is the one with MvxPropertyInfoTargetBinding. Here is the code working ok for me:
public class MvxUISegmentedControlSelectedSegmentTargetBinding : MvxPropertyInfoTargetBinding<UISegmentedControl>
{
public MvxUISegmentedControlSelectedSegmentTargetBinding(object target, PropertyInfo targetPropertyInfo)
: base(target, targetPropertyInfo)
{
this.View.ValueChanged += HandleValueChanged;
}
private void HandleValueChanged(object sender, System.EventArgs e)
{
var view = this.View;
if (view == null)
{
return;
}
FireValueChanged(view.SelectedSegment);
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.TwoWay; }
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (isDisposing)
{
var view = this.View;
if (view != null)
{
view.ValueChanged -= HandleValueChanged;
}
}
}
}
public class Setup : MvxTouchSetup
{
...
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
registry.RegisterPropertyInfoBindingFactory(typeof(MvxUISegmentedControlSelectedSegmentTargetBinding), typeof(UISegmentedControl), "SelectedSegment");
}
}

How to close user control used in radgrid filtering?

I have a radgrid, for date column i have created a custom user control for filtering. I need to create a close button to close the user control. There are no close events which i can call. I don't want to make visibility collapsed. I started with something below:
public partial class DateFilterControl : UserControl, IFilteringControl
{
public event CloseEventHandler Close;
public delegate void CloseEventHandler();
private void Button_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
It is throwing nullreference exception which is obvious to come. What code do i need to put to close the user control?
use Messaging Service. With this you can close the window in ViewModel so no need to give close function in Backend. Add Command property to Cancel button
<Button Content="Cancel" Command="{Binding CancelCommand}"/>
Now in the ViewModel add the RelayCommand property in that add
Messenger.Default.Send<bool>(true, typeof(XViewModel));
Now in the BackEnd of this userControl adds following in the constructor.
Messenger.Default.Register<bool>(this, typeof(ScheduleViewModel), (b) =>
{
if (b == true)
{
this.DialogResult = true;
}
});
Now u can close the Window...
This will surely helps u...

Resources