I am developing a windows phone application. In that I wanted a functionality such that if a text box gets focus date picker should be opened. Similarly another text box will trigger a time picker.
i searched and found that this can be achieved with writing a custom date/time picker. I successfully got the time picker working in this fashion but when I tried to implement the same method for date picker I'm getting the following exception.
"Error HRESULT E_FAIL has been returned from a call to a COM component."
The XAML code for the time and date picker are as follows.
<popUps:CustomTimePicker x:Name="timePicker" Visibility="Collapsed" Value="{Binding SelectedTime, Converter={StaticResource dateTimeConverter}, Mode=TwoWay}" />
<popUps:CustomDatePicker x:Name="datePicker" Visibility="Collapsed" />
The custom date picker class which I wrote for the same is
class CustomDatePicker : DatePicker
{
public void ClickDateTemplateButton()
{
ApplyTemplate();
Button button = (GetTemplateChild("DateTimeButton") as Button);
if (button != null)
{
ButtonAutomationPeer peer = new ButtonAutomationPeer(button);
if (peer != null)
{
IInvokeProvider provider = (peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider);
if (provider != null)
{
provider.Invoke();
}
}
}
}
}
Please help me finding where it went wrong. Thanks.
As a workaround, don't add the customDatePicker in your listBoxItem DataTemplate.
Whenever you want to launch the controls, call the following method. You will need to save the index of your selected listBoxItem in your page's transient State in order to populate the correct Item of your listbox with the selected value, after you return to your page, when the datepicker page closes.
private void LanchDatePicker()
{
datepicker = new CustomDatePicker
{
IsTabStop = false,
MaxHeight = 0,
Value = null
};
datepicker.ValueChanged += DatePicker_OnValueChanged;
LayoutRoot.Children.Add(datepicker);
datepicker.ClickTemplateButton();
}
Related
I am using Xamarin Forms to make Cross-platform application and I need to create simple view that user can choose date and time, similar to this:
View that I want to create that i found here: Picker in Xamarin iOS. Solution for Android is ready, but I need to create solution for iOS in the same application
I can not use standard date picker and another standard time picker separately from Xamarin Forms. I need to create custom solution (one view - simple choose both date and time).
I have tried to create view in Xamarin Forms that consist of 2 lists in horizontal orientation (one for date, one for time) but when I select one position, the list is not scrolling to the middle of view and also there is not auto-selecting middle position element when I scroll the list up or down. I want to create something that works like Xamarin-iOS solution: "Date and time picker" but in Xamarin Forms.
I have tried also to create in Xamarin-iOS part of project "date and time picker". I have main.storyboard and view controller but I dont know how to display view from Xamarin-iOS inside Xamarin Forms and pass selected date and time.
Can you help me, please?
If you want to implement date-time picker on Xamarin.Forms in iOS platform.You can use CustomRenderer.
in Forms
create a subclass of Picker
public class MyPicker:Picker
{
public MyPicker()
{
}
}
And add it in xaml
<StackLayout VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
<!-- Place new controls here -->
<local:MyPicker WidthRequest="150" BackgroundColor="AliceBlue"/>
</StackLayout>
in iOS
create the renderer of Picker .And you can set the format of picker as you want.
using System;
using Foundation;
using UIKit;
using ObjCRuntime;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using xxx;
using xxx.iOS;
[assembly:ExportRenderer(typeof(MyPicker),typeof(MyPickerRenderer))]
namespace xxx.iOS
{
public class MyPickerRenderer:PickerRenderer
{
string SelectedValue;
public MyPickerRenderer()
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
if(Control!=null)
{
SetTimePicker();
}
}
void SetTimePicker()
{
UIDatePicker picker = new UIDatePicker
{
Mode = UIDatePickerMode.DateAndTime
};
picker.SetDate(NSDate.Now,true);
picker.AddTarget(this,new Selector("DateChange:"),UIControlEvent.ValueChanged);
Control.InputView = picker;
UIToolbar toolbar = (UIToolbar)Control.InputAccessoryView;
UIBarButtonItem done = new UIBarButtonItem("Done", UIBarButtonItemStyle.Done, (object sender, EventArgs click) =>
{
Control.Text = SelectedValue;
toolbar.RemoveFromSuperview();
picker.RemoveFromSuperview();
Control.ResignFirstResponder();
MessagingCenter.Send<Object, string>(this, "pickerSelected", SelectedValue);
});
UIBarButtonItem empty = new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace, null);
toolbar.Items = new UIBarButtonItem[] { empty, done };
}
[Export("DateChange:")]
void DateChange(UIDatePicker picker)
{
NSDateFormatter formatter = new NSDateFormatter();
formatter.DateFormat = "MM-dd HH:mm aa"; //you can set the format as you want
Control.Text = formatter.ToString(picker.Date);
SelectedValue= formatter.ToString(picker.Date);
MessagingCenter.Send<Object, string>(this,"pickerSelected",SelectedValue);
}
}
}
And use MessagingCenter to pass the selected date and time.
public MainPage()
{
InitializeComponent();
MessagingCenter.Subscribe<Object, string>(this, "pickerSelected", (sender, arg) => {
Console.WriteLine(arg);
//arg is the selected date and time
});
}
I have uploaded the demo on github .You can download it for test.
The effect
If you want to use native views in Xamarin.Forms it is possible, read it here: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/platform/native-views/
I am making a Universal Windows App, which includes inserting text into a textbox. I want my app to suggest text from a file to insert to the textbox. But I could not find that property. I have added the textbox in the MainPage.xaml through XAML tags. I believe there is a property for this operation in WPF API. I am just not sure if I can do this in UWP.
I recommend using the AutoSuggestBox control for UWP. The auto-suggest results list populates automatically once the user starts to enter text. The results list can appear above or below the text entry box.
<AutoSuggestBox PlaceholderText="Search" QueryIcon="Find" Width="200"
TextChanged="AutoSuggestBox_TextChanged"
QuerySubmitted="AutoSuggestBox_QuerySubmitted"
SuggestionChosen="AutoSuggestBox_SuggestionChosen"/>
private void AutoSuggestBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
{
// Only get results when it was a user typing,
// otherwise assume the value got filled in by TextMemberPath
// or the handler for SuggestionChosen.
if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput)
{
//Set the ItemsSource to be your filtered dataset
//sender.ItemsSource = dataset;
}
}
private void AutoSuggestBox_SuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args)
{
// Set sender.Text. You can use args.SelectedItem to build your text string.
}
private void AutoSuggestBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
{
if (args.ChosenSuggestion != null)
{
// User selected an item from the suggestion list, take an action on it here.
}
else
{
// Use args.QueryText to determine what to do.
}
}
Here is the link to the GitHub repo for a complete UI basics sample.
Hope this helps.
This may not apply for UAP but with WPF there's a trick that allows a "dropdown suggestion list". You can replace text box with a combobox and populate it's items when user types. This can be achieved by doing bindings like so:
Text={ Binding Path=meCurrentValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged }
ItemsSource={Binding Path=meFilteredListOfSuggestions, Mode=TwoWay }
Then within your viewmodel you can simply do:
public string meCurrentValue
{
get { return _mecurrentvalue; }
set {
_mecurrentvalue = value;
updateSuggestionsList();
NotifyPropertyChanged("meCurrentValue");
NotifyPropertyChanged("meFilteredListOfSuggestions"); // notify that the list was updated
ComboBox.Open(); // use to open the combobox list
}
public List<string> meFilteredListOfSuggestions
{
get{return SuggestionsList.Select( e => e.text.StartsWith(_mecurrentvalue));}
}
EDIT:
Remember to set the editable value of the combobox to TRUE, this way it will act like a normal textbox.
I have a WPF application with multiple tabs. Under each tab, a user can change some settings (using CheckBoxes, TextBoxes, etc) and then the user must click the "Update" button in order to save those settings. Everything works fine but one of requirements is to alert the user if he tries to switch to other tab without clicking the "Update" button.
So I'm trying to use the
TabItem_LostFocus
event handler to achieve it but this event is triggered every time I click on something within the tab. I guess I can patch this issue by placing
e.Handled = true
for every control I have but this doesn't sound like an elegant solution (especially when I don't have click event handlers for everything under my tabs). Is there some other way to determine when you are switching away from the current tab?
Thank you
To achieve your requirement, you just need to data bind to the TabControl.SelectedIndex or the TabControl.SelectedItem properties:
<TabControl ItemsSource="{Binding TabItemCollection}"
SelectedItem="{Binding SelectedTabItem}" />
Then in your view model or code behind:
private YourDataType selectedItem;
public YourDataType SelectedItem
{
get { return selectedItem; }
set
{
// selectedItem represents the previous TabItem
// value represents the new TabItem
selectedItem = value;
}
}
You can bind to the IsSelected property of each TabItem.. and then do your checking inside the setter
<TabControl>
<TabItem IsSelected="{Binding TabItem1IsSelected}"/>
</TabControl>
Property:
public bool TabItem1IsSelected
{
get { return _tabItem1IsSelected; }
set
{
if (_tabItem1IsSelected)
{
if (!value)
{
// Check to see if user has updated
if (!userUpdated)
{
value = true;
}
}
}
_tabItem1IsSelected = value;
RaisePropertyChanged();
}
}
I have a very strange Problem:
On my machine the DatePicker changes its watermark AND date-format according to the language/culture i want to set.
If i copy my application to other computers following happens:
On some computer it works like it does on my machine. On other computers only the date-format changes but the watermark does not! Needless to say it is very ugly to have a datepicker with e.g. a german date but an english watermark.
What is the cause for that behaviour?
For i18n i use following code:
App.xaml.cs:
public partial class App : Application
{
public App()
{
CultureInfo ci = new CultureInfo("de-DE");
Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;
}
}
WindowMain.xaml.cs:
public partial class WindowMain : RibbonWindow
{
public WindowMain()
{
this.Language = XmlLanguage.GetLanguage("de-DE");
this.InitializeComponent();
}
}
It's actually really easy to set the watermarked text:
<DatePicker>
<DatePicker.Resources>
<Style TargetType="DatePickerTextBox">
<Setter Property="Text" Value="Watermark Text"/>
</Style>
</DatePicker.Resources>
</DatePicker>
http://www.admindiaries.com/change-datepicker-watermark-in-wpf/
One thing I can say, Watermark in DatePicker implemented buggy, there is no easy access. Perhaps, because of this difficulty, the localization of the text does not work. There is a wonderful article of #Matt Hamilton, quote from here:
Something that a lot of people (myself included) don't like about the DatePicker, though, is that by default if no date is displayed it shows the text "Select a date" as a watermark, and this text is baked into the control - it's not localized or accessible by any public property. This is particularly frustrating if the date in question is optional and you don't necessarily want to prompt your users to select one.
In the same article, he provide the decision of how to access to Watermark. Here:
How to localize the WPF 4.0 DatePicker control
#Wayne Maurer created a universal solution in the form of attached dependency property:
<DatePicker Grid.Row="2"
local:DatePickerWatermarkBehaviour.Watermark="Select the date" />
You need to be based on the current culture, set the text for watermarks, e.g. using above example.
Note: In Silverlight to Watermark in DatePicker made access [link]:
DatePickerTextBox box = base.GetTemplateChild("TextBox") as DatePickerTextBox;
box.Watermark = "Type or select a date --> ";
Wayne solution works great but does not work when DatePicker is part of DataGridColumnHeader and sometimes when DatePicker is on control that is first hidden and then visible. Matt Hamilton's solution works only onLoad, and when you change selectedDate there is again annoying Select a date watermark. The easiest solution is just to override OnRender event in custom class. If you set watermark property and not a watermark content that you need to override onload event as well. Complete class is here:
public class myDateTimePicker : DatePicker
{
public string Watermark { get; set; }
protected override void OnSelectedDateChanged(SelectionChangedEventArgs e)
{
base.OnSelectedDateChanged(e);
//SetWatermark();
}
protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
{
base.OnRender(drawingContext);
SetWatermark();
}
private void SetWatermark()
{
FieldInfo fiTextBox = typeof(DatePicker).GetField("_textBox", BindingFlags.Instance | BindingFlags.NonPublic);
if (fiTextBox != null)
{
DatePickerTextBox dateTextBox = (DatePickerTextBox)fiTextBox.GetValue(this);
if (dateTextBox != null)
{
if (string.IsNullOrWhiteSpace(this.Watermark))
{
this.Watermark = "Custom watermark";
}
// if you set property this way then you need to override OnSelectedDateChanged event
//PropertyInfo piWatermark = typeof(DatePickerTextBox).GetProperty("Watermark", BindingFlags.Instance | BindingFlags.NonPublic);
//if (piWatermark != null)
//{
// piWatermark.SetValue(dateTextBox, this.Watermark, null);
//}
var partWatermark = dateTextBox.Template.FindName("PART_Watermark", dateTextBox) as ContentControl;
if (partWatermark != null)
{
partWatermark.Foreground = new SolidColorBrush(Colors.Gray);
partWatermark.Content = this.Watermark;
}
}
}
}
}
I am trying to migrate a small prototype application I made in WinForms to WPF. I'm having some issues with a combobox in WPF not changing values when I select a different value from the drop-down. Initially, I tried just copying the code that I used in my WinForms app to populate the combobox and determine if a new index had been selected. This is how my WinForms code looked like:
private void cmbDeviceList_SelectedIndexChanged(object sender, EventArgs e)
{
var cmb = (Combobox) sender;
var selectedDevice = cmb.SelectedItem;
var count = cmbDeviceList.Items.Count;
// find all available capture devices and add to drop down
for(var i =0; i<count; i++)
{
if(_deviceList[i].FriendlyName == selectedDevice.ToString())
{
_captureCtrl.VideoDevices[i].Selected = true;
break;
}
}
}
Earlier in the code, I am populating the _deviceList List and the combo box (in Form1_Load to be specific) by looping over the available devices and adding them. I tried the same approach in WPF and could only populate the combo box. When I selected a new value, for some reason the same exact value (the initial device) was being sent into the event code (cmbCaptureDevices_SelectionChanged in my WPF app). I looked around for some tutorials in WPF and found that maybe data binding was my issue, and I tried that out instead. This is my combobox in my XAML file:
<ComboBox ItemsSource="{Binding Devices}" Name="cmbCaptureDevices"
IsSynchronizedWithCurrentItem="True" SelectedItem="{Binding CurrentDevice,
Mode=TwoWay}" Se;ectionChanged="cmbCapturedDevices_SelectionChanged" />
There's more to that XAML definition, but it's all arbitrary stuff like HorizontalAlignment and whatnot. My VideoDevicesViewModel inherits from INotifyPropertyChanged, has a private List<Device> _devices and a private Device _currentDevice. The constructor looks like:
public VideoDevicesViewModel()
{
_devices = GetCaptureDevices();
DevicesCollection = new CollectionView(_devices);
}
GetCaptureDevices simply is the loop that I had in my WinForms app which populates the list with all avaialble capture devices on the current machine. I have a public CollectionView DevicesCollection { get; private set; } for getting/setting the devices at the start of the application. The property for my current device looks like:
public Device CurrentDevice
{
get { return _currentDevice; }
set
{
if (_currentDevice = value)
{
return;
}
_currentDevice = value;
OnPropertyChanged("CurrentDevice");
}
}
OnPropertyChanged just raises the event PropertyChanged if the event isn't null. I'm new to WPF (and pretty new to C# in general, honestly) so I'm not sure if I'm missing something elementary or not. Any idea as to why this combobox won't change values for me?
Discovered the answer on my own here. The unexpected behavior was a result of using the Leadtools Device class. It's a COM component and apparently was not playing nicely with my application. I honestly don't understand why exactly it worked, but I wrapped the Device class in another class and used that instead. As soon as I was using the wrapper class, the combo box functioned as it should.
You are using the assignment operator '=' instead of the equality operator '=='
Change
if (_currentDevice = value)
to
if (_currentDevice == value)
Try the following
if _currentDevice == value ...