I have following XAML -
<TextBox Text="{Binding Path=NumberOfItems, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
<Button Command="{Binding Path=StartCommand}">Start</Button>
In ViewModel -
public string this[string columnName]
{
get
{
string result = null;
switch (columnName)
{
case "NumberOfItems":
if (this.NumberOfItems <= 0)
{
result = "Items required";
}
break;
}
return result;
}
}
Whenever, TextBox changes values the trigger works accordingly. But in following cases, It is not working -
When user presses delete button in keyboard after selecting whole text of textbox.
When user deletes the last character present in TextBox.
however ValidatesOnDataError is working.
How can I make it work when TextBox empties?
When user enters any invalid data, TextBox Style changes. I want this to be known in click of Start Button.
How can I make aware the Start button that TextBox has invalid data?
I am guessing you are trying to Bind a property of type integer to the text property of your textbox. Since integers cannot be null, empty string will not work in this case. You can use either nullable integer or you can create your own converter to handle empty string.
When user enters any invalid data, TextBox Style changes. I want this to be known in click of Start Button.
How can I make aware the Start button that TextBox has invalid data?
change your validation code to:
case "NumberOfItems":
if (this.NumberOfItems==null || this.NumberOfItems <= 0)
{
result = "Items required";
}
break;
You can check string.IsNullOrEmpty(this["NumberOfItems"]) within the CanExceuteStartCommand of your StartCommand
Related
I have a problem to reset a dropdownlist is c# I have hiden and showed dropdown's depending on a value in the first selection dropdown box my code did work but i remembered you can type in a combobox and changed it to dropdownlist in visual studio and after that nope not working anymore. so basically i don't want the items to be removed from list it must just be at the starting "empty value" like it was when program loaded here is the code that worked before the change
if(serviceFault_cb.Text == "Report Fault")
{
serviceType_cb.Text = "";
serviceType_cb.Hide();
serviceType_lb.Hide();
faultMain1_lb.Show();
faultMain1_cb.Show();
}
else if (serviceFault_cb.Text == "Service and Faults")
{
serviceType_cb.Show();
serviceType_lb.Show();
faultMain1_lb.Show();
faultMain1_cb.Show();
}
else
{
serviceType_cb.Show();
serviceType_lb.Show();
faultMain1_cb.Text = "";
faultMain1_lb.Hide();
faultMain1_cb.Hide();
}
a basic if statement to hide and show combobox's just need the value to clear when box is hidden and loaded again
Add an empty item into each combobox that would work as a deselected value.
Add it before you add the actual items, then you can deselect a value by doing
serviceType_cb.SelectedIndex = 0;
panel_erviceType.Show();
Also I'd suggest using a panel to encapsulate the combobox with it's corresponding label to hide them simultaneously.
I have a DateTimePicker as follows:
<UserControl
...
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
...
>
<xctk:DateTimePicker Name="MyDatePicker"
Value="{Binding MyDate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"
Format="Custom" FormatString="dd/MM/yyyy HH:mm:ss"
AutoCloseCalendar="True"/>
I'm using IDateErrorInfo on my data model to handle business logic errors; for example:
public class MyViewModel : IDataErrorInfo
{
public string Error
{
get { return null; }
}
public string this[string columnName]
{
get
{
string error = DataValid();
CanExecute = (error == string.Empty);
return error;
}
}
CanExecute is a property which manages whether the user can select to submit the data. This all works well, however, if I simply select the date and mash the keyboard (type random letters), the date is reset to 01/01/01. What I would like to happen is for the date to effectively remain unchanged (that is, as it was before I mashed the keyboard). However, I can't seem to find a place to handle the casting error which obviously is occurring when this happens.
How can I trap this?
(The DateTimePicker control is part of the WPF Extension Kit)
If you don't like the way the control handles errors you can handle errors yourself in a subclass, an example of this in my old question Wpf Datepicker Input modification
I've been working on an application in MVVM Light lately. I have a TextBox in my XAML bound to my UI. I'd like to validate any input and ensure that only numbers are entered. I've tried the following code:
My TextBox:
<TextBox TabIndex="1" Height="23" MinWidth="410" DockPanel.Dock="Left"
HorizontalAlignment="Left"
Text="{Binding Input, UpdateSourceTrigger=PropertyChanged}"
IsEnabled="{Binding IsEnabled}"
AcceptsReturn="False"
local:FocusExtension.IsFocused="{Binding IsFocused}">
And in my ViewModel:
private string input;
public string Input
{
get { return this.input; }
set
{
decimal test;
if(decimal.TryParse(value, out test))
{
this.input = value;
}
else
{
this.input = "";
}
RaisePropertyChanged("Input");
}
}
This fails to update the UI. If I enter "B" and check the debugger, it runs through the setter, but fails to actually update the UI.
Curiously, if I set this.input = "TEST"; in the else block, the UI updates, but, if I attempt to set it to "", string.Empty, or the value of input before the validation, the UI fails to update.
Is this by design? Possibly a bug? Is there something I'm doing wrong?
Edit I mistakenly forgot to include RaisePropertyChanged in my example code. I've updated it. Raising it isn't the problem as I've watched the debugger run all the way through raising it and returning input via the getter.
Way you use strign type property and then convert to decimal, easier to change lik this:
public decimal Input
{
get { return this.input; }
set
{
this.input = value;
RaisePropertyChanged("Input");
}
}
And for validate use IDataErrorInfo (read more: http://blogs.msdn.com/b/wpfsdk/archive/2007/10/02/data-validation-in-3-5.aspx)
What we have done is created a Custom Control, since we use it for a Currency Text Box. I warn you I have no validation that this is a good idea, or falls in line with MVVM model because all manipulation of the control are done in code behind.
In the control on the textbox we have an event on PreviewTextInput that does this
e.Handled = Functions.DoubleConverter(Convert.ToChar(e.Text), ((TextBox)sender).Text.Replace("$", ""));
Then for the function (which isnt perfect, I have a few issues with it still) is:
static public bool DoubleConverter(char c, string str)
{
if (!char.IsDigit(c))
{
if (c == '.' && (str.Contains('.')))
{
return true;
}
else if (c != '.')
{
return true;
}
}
return false;
}
Please use this as a reference, not exactly as is because it is a very crude implementation.
I am trying to filter a list of items in a ListView as the user types into a TextBox and I use KeyDown, and KeyPress events but when I read the textbox.Text, it always returns the text before the last key press. Is there a way to always get whatever is shown in the TextBox without pressing enter?
Use the TextBox.TextChanged event (inherited from Control).
Occurs when the Text property value changes.
My advice is to try not to hack this with the key events (down / press / up) - there are other ways to change a text-box's text, such as by pasting text from the right-click context menu. This doesn't involve pressing a key.
You could use the TextChanged event of the TextBox in question. I think the KeyUp event might work as well.
The previous answers are incomplete with regards to the actual original question: how to retrieve the contents of the Text property when the user has just pressed a key (and including that keypress)?
The KeyUp event happens to be fired AFTER the contents of the Text property actually change, so using this particular order of events, you can retrieve the latest value of the text contents just using a KeyUp event handler.
The KeyPress event doesn't work because that gets fired BEFORE the change of the Text property.
Use the KeyPressEventArgs.KeyChar Property.
public static string NextControlValue(string originalValue, int selectStart, int selectLength, string keyChar)
{
if (originalValue.Length > selectStart)
{
if (selectLength > 0)
{
originalValue = originalValue.Remove(selectStart, selectLength);
return NextControlValue(originalValue, selectStart, 0, keyChar);
}
else
{
return originalValue.Insert(selectStart, keyChar);
}
}
else
{
return originalValue + keyChar;
}
}
var previewValue = NextControlValue(textbox.Text, textbox.SelectionStart, textbox.SelectionLength, e.KeyChar + "");
You can try with KeyPress event:
int position = textBox1.SelectionStart;
string changedText = textBox1.Text.Insert(position, e.KeyChar.ToString());
How can I force the redisplay of the value of the UpDown box?
I have an application that has a number of UpDown boxes for setting values of a configuration file before loading the file onto an embedded device. I can load a configuration from the device and display the values in the appropriate UpDown boxes.
However, if I delete the contents of an UpDown box and then update it's value, the value of the updown box does not get redrawn unless I increment or decrement the value with the integrated buttons.
Steps to take to reproduce:
Start App.
Delete value from UpDown box so it displays nothing
Change the UpDownBox's .Value, there is still no value displayed.
Increment or decrement the UpDown box with the buttons, the correctly changed value is displayed.
I have tried the following with no change.:
fenceNumberUpDown.Value = config.getFenceNumber();
fenceNumberUpDown.Refresh();
fenceNumberUpDown.Update();
fenceNumberUpDown.ResetText();
fenceNumberUpDown.Select();
fenceNumberUpDown.Hide();
fenceNumberUpDown.Show();
fenceNumberUpDown.Invalidate();
Here's a couple of workarounds I was able to come up with or may give you some other ideas to solve the problem.
Workaround #1: Call UpButton() before setting the value.
this.numericUpDown1.UpButton();
this.numericUpDown1.Value = 20;
Workaround #2: Extend NumericUpDown and overide the Value property.
public class NumericUpDownNew : NumericUpDown
{
public new decimal Value
{
get { return base.Value; }
set
{
string text = "";
if(this.ThousandsSeparator)
text = ((decimal)value).ToString("n" + this.DecimalPlaces);
else
text = ((decimal)value).ToString("g" + this.DecimalPlaces);
Controls[1].Text = text;
base.Value = value;
}
}
}
I just faced this same issue, and I found another workaround which some users may prefer:
numUpDown.Text = " ";
numUpDown.Value = 12.34m;
Just setting the Text (a hidden property which IntelliSense doesn't suggest but exists though) to a non-numeric value (but not empty) forces the control to render the new value. If you don't assign Value any number afterwards, it will restore the last valid value the control had.