ToggleButton is always true MVVM WPF - c#

I have a little problem. I have 3 states for a togglebutton - two checked and one unchecked, but it is always checked. I don't know why.
XAML:
<ToggleButton Grid.Row="0" Grid.Column="1" Style="{DynamicResource MetroCircleToggleButtonStyle}" IsChecked="{Binding Path=RepeatChecked}" Command="{Binding Path=RepeatCommand}">
<Image Source="../Ressources/repeat.png"></Image>
</ToggleButton>
C#:
private void RepeatFunction()
{
if (!this.RepeatChecked)
{
Console.WriteLine("Not checked");
this.RepeatChecked = true;
this.stateRepeat = StateRepeat.ONE;
}
else if (this.RepeatChecked && this.stateRepeat == StateRepeat.ONE)
{
Console.WriteLine("Not checked - 2");
this.RepeatChecked = true;
this.stateRepeat = StateRepeat.ALL;
}
else if (this.RepeatChecked)
{
Console.WriteLine("Checked");
this.RepeatChecked = false;
this.stateRepeat = StateRepeat.NONE;
}
}
The console write is always Checked. I really don't understand.
EDIT:
this.stateRepeat = StateRepear.NONE;
this.RepeatCommand = new CommandProvider(obj => RepeatFunction());

The problem is that on click of toggle button, you always set the RepeatChecked to false/true which is bind to IsChecked which updates toggle state sets unchecked/checked again; so checked changes to unchecked and unchecked changes to check. Comment the line in all three conditions and run the flow and you will see all conditions working.
private void RepeatFunction()
{
if (!this.RepeatChecked)
{
Console.WriteLine("Not checked");
////this.RepeatChecked = true;
this.stateRepeat = StateRepeat.ONE;
}
else if (this.RepeatChecked && this.stateRepeat == StateRepeat.ONE)
{
Console.WriteLine("Not checked - 2");
////this.RepeatChecked = true;
this.stateRepeat = StateRepeat.ALL;
}
else if (this.RepeatChecked)
{
Console.WriteLine("Checked");
////this.RepeatChecked = false;
this.stateRepeat = StateRepeat.NONE;
}
}

Related

Numbers not updating on view and On Appearing not helpful

I have method for deleting a word from a dictionary. Deleting works fine and when I debug the method I can see that the correct amount is being transferred to the UI however the UI doesn't update here I can see there is the correct amount
AmountOfWordsInDictionary = _allWordsOfUser?.Count ?? default;
It updates once I leave and come back. FYI my notify view works fine on any other part of my page, I have also tried on appearing but that is not very helpful
Can you please advise
public int AmountOfWordsInDictionary
{
set
{
_amountOfWordsInDictionary = value;
NotifyPropertyChanged(nameof(AmountOfWordsInDictionary));
}
get { return _amountOfWordsInDictionary; }
}
My method:
private async void RemoveWordFromUserDictionary()
{
if (!wordIsRemoving && !viewDisabled)
{
wordIsRemoving = true;
if (NetworkDelegate.IsOnline)
{
var wordRemovedApiResponse = await App.ApiFactory.RemoveWordFromUserDictionaryAsync(_word, LoggedUser.CurrentUser.Id);
if (wordRemovedApiResponse.ApiResponse == ApiResponse.Ok)
{
FindAnotherWordInDictionary();
_allWordsOfUser = App.ApiFactory.GetAllWordsOfUserLocal();
AmountOfWordsInDictionary = _allWordsOfUser?.Count ?? default;
}
else
{
NotificationService.ShowToast("something is wrong");
}
}
else
{
await App.ApiFactory.RemoveWordFromUserDictionaryLocalAsync(_word, LoggedUser.CurrentUser.Id);
FindAnotherWordInDictionary();
_allWordsOfUser = App.ApiFactory.GetAllWordsOfUserLocal();
**AmountOfWordsInDictionary** = _allWordsOfUser?.Count ?? default;
**// have also tried _amountOfWordsInDictionary**
}
wordIsRemoving = false;
}
}
My xaml :
<Label
Grid.Row="0"
Grid.Column="1"
Margin="0"
FontSize="15"
HorizontalOptions="End"
IsVisible="{grial:OnOrientationBool Default='true',
LandscapePhone='false'}"
Text="{Binding AmountOfWordsInDictionary,Mode=TwoWay}"
TextColor="{DynamicResource CircleActionButtonFlatTextColor}"
VerticalOptions="Start" />
public Dictionary()
{
InitializeComponent();
BindingContext = new DictionaryViewModel();
}

How to disable the marking of first input

I created a editable ComboBox for searching(filtering) like Google. I am using the ActionHandler "KeyUp" and the first input is highlighted and overwritten. How can i disable the overwriting or highlighting?
private void CbInKuLi_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
CollectionView itemsViewOriginal = (CollectionView)CollectionViewSource.GetDefaultView(cbInKuLi.ItemsSource);
itemsViewOriginal.Filter = ((o) =>
{
if (String.IsNullOrEmpty(cbInKuLi.Text)) return true;
else
{
DeKreditor x = (DeKreditor)o;
string filterText = cbInKuLi.Text;
if (x.Nummer.ToLowerInvariant().Contains(filterText)
|| (!string.IsNullOrWhiteSpace(x.Firma) && x.Firma.ToLowerInvariant().Contains(filterText))
|| (!string.IsNullOrWhiteSpace(x.Vorname) && x.Vorname.ToLowerInvariant().Contains(filterText))
|| (!string.IsNullOrWhiteSpace(x.Name) && x.Name.ToLowerInvariant().Contains(filterText)))
return true;
else
return false;
}
});
itemsViewOriginal.Refresh();
cbInKuLi.IsDropDownOpen = true;
}
XAML:
<ComboBox
x:Name="cbInKuLi"
StaysOpenOnEdit="True"
IsEditable="True"
IsTextSearchEnabled="False"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Grid.Row="0"
Grid.Column="1"
Margin="5,0,5,5"
SelectionChanged="CbInKuLi_SelectionChanged"
KeyUp="CbInKuLi_KeyUp"
TextOptions.TextFormattingMode="Ideal" />
The Text Highlight caused because of setting IsDropDownOpen to true.
The Editable ComboBox auto select the Text if it is Opened, so you could get the TextBox from the template of the ComboBox by its Name than set the selection length to zero at the end of the text.
private void CbInKuLi_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
CollectionView itemsViewOriginal = (CollectionView)CollectionViewSource.GetDefaultView(cbInKuLi.ItemsSource);
itemsViewOriginal.Filter = ((o) =>
{
if (String.IsNullOrEmpty(cbInKuLi.Text)) return true;
else
{
Model x = (Model)o;
string filterText = cbInKuLi.Text;
if (x.Text.ToLowerInvariant().Contains(filterText))
return true;
else
return false;
}
});
itemsViewOriginal.Refresh();
cbInKuLi.IsDropDownOpen = true;
var textbox = (TextBox)cbInKuLi.Template.FindName("PART_EditableTextBox", cbInKuLi);
textbox.Select(textbox.Text.Length, textbox.Text.Length);
}
UPDATE:
From comments you can replace the last line by the following line and it is better than the original one:
textbox.CaretIndex = textbox.Text.Length;

change 'isenabled' for wpf texbox in usercontrol (codebehind)

Code in context
private void button2_Click(object sender, RoutedEventArgs e)
{
edit();
}
public void edit()
{
textBox1.IsEnabled = true;
textBox2.IsEnabled = true;
textBox3.IsEnabled = true;
textBox4.IsEnabled = true;
textBox5.IsEnabled = true;
textBox6.IsEnabled = true;
textBox7.IsEnabled = true;
textBox8.IsEnabled = true;
textBox9.IsEnabled = true;
textBox10.IsEnabled = true;
textBox11.IsEnabled = true;
textBox12.IsEnabled = true;
textBox13.IsEnabled = true;
textBox14.IsEnabled = true;
textBox15.IsEnabled = true;
textBox16.IsEnabled = true;
textBox17.IsEnabled = true;
textBox18.IsEnabled = true;
}
I want perform the above using a simple for loop that loops through 1-18.
I have tried the followng method but doesn't work as intended
for(i=0;i<19;i++)
{
textBox"" + i + "".IsVisible = true;
}
I'm new to wpf and i'm migrating my app from winforms to wpf.
Use binding.
XAML (MyUserControl):
<UserControl Name="MyControl" ...
....
<TextBox Name="textBox1" IsEnabled="{Binding ElementName=MyControl, Path=AreTextBoxesEnabled}" ... />
<TextBox Name="textBox2" IsEnabled="{Binding ElementName=MyControl, Path=AreTextBoxesEnabled}" ... />
<TextBox Name="textBox3" IsEnabled="{Binding ElementName=MyControl, Path=AreTextBoxesEnabled}" ... />
...
Code-behind (MyUserControl):
public static readonly DependencyProperty AreTextBoxesEnabledProperty = DependencyProperty.Register(
"AreTextBoxesEnabled",
typeof(bool),
typeof(MyUserControl));
public bool AreTextBoxesEnabled
{
get { return (bool)GetValue(AreTextBoxesEnabledProperty); }
set { SetValue(AreTextBoxesEnabledProperty, value); }
}
Just calling AreTextBoxesEnabled = true; will make all the textboxes enabled.
Of course, there are many many other ways. But this is the basic way (without MVVM) of doing it, by harnessing the power of binding.
Simple solution (but not recommended) way is as simple as:
for (i = 0; i < 19; i++)
{
var tb = this.FindName("textBox" + i.ToString()) as TextBox;
if (tb != null) tb.IsEnabled = true;
}
Create a list of text boxes like:
var textBoxes = new List<TextBox>();
// Btw, I don't have a compiler by hand, I assume the type is TextBox.
Fill textBoxes:
textBoxes.Add(textBox1);
textBoxes.Add(textBox2);
...
textBoxes.Add(textBox18);
This is a one-time manual action to fill it. Afterwards you can loop through them:
foreach (var textBox in textBoxes)
{
textBox.IsVisible = true;
}
Or use any other setting/algorithm on the text boxes with the foreach loop (or for, linq etc).

FullscreenBehaviour for Mahapps

How to add a dynamic switching ability from fullscreen to windowed mode and vice versa to Mahapps MetroWindow?
Starting with Normal Window
and after switching to fullscreen the top right window Buttons (Minimize/Maximize/Close) are still visible (but they shouldn't be visible as well as the title bar). The reserved space for the title bar seems to be still there.
The other way round initially from fullscreen state (no buttons, except the Hello button in the middle and no title bar => as expected)
... but when switching back to normal window state the title is back again but the top left buttons are missing.
Am I doing something wrong here in the code? I used an derrived Behaviour. The interesting part that is executed when switching is this:
private static void OnIsFullscreenChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var window = (MetroWindow)sender;
var oldValue = (bool)e.OldValue;
var newValue = (bool)e.NewValue;
if (newValue == oldValue || window == null)
{
return;
}
if (newValue)
{
window.Tag = window.WindowState;
window.Topmost = true;
window.UseNoneWindowStyle = true;
window.IgnoreTaskbarOnMaximize = true;
window.ShowTitleBar = false;
window.WindowStyle = WindowStyle.None;
window.WindowState = WindowState.Maximized;
}
else
{
window.Topmost = false;
window.UseNoneWindowStyle = false;
window.IgnoreTaskbarOnMaximize = false;
window.ShowTitleBar = true;
window.WindowStyle = WindowStyle.SingleBorderWindow;
window.WindowState = (WindowState)window.Tag;
}
}
Attaching a simular Behaviour to a default Window WPF control everything works as expected.
I attach the Behaviour this way:
<controls:MetroWindow ... local:FullscreenBehavior.IsFullscreen="{Binding Fullscreen}">
<!-- code above sets initial state depending on ViewModel value -->
<!-- code below fires mode switching when a defined key is pressed => executes OnIsFullscreenChanged method -->
<i:Interaction.Behaviors>
<behaviours:BorderlessWindowBehavior />
<behaviours:WindowsSettingBehaviour />
<behaviours:GlowWindowBehavior />
<modern:FullscreenBehavior FullscreenKey="{Binding FullscreenKey}" />
</i:Interaction.Behaviors>
...
EDIT: Set state of Window Buttons explicitly
When I extend the method to set the states to the correct value explicitly there seems to be another strange effect:
private static void OnIsFullscreenChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var window = (MetroWindow)sender;
var oldValue = (bool)e.OldValue;
var newValue = (bool)e.NewValue;
if (newValue == oldValue || window == null)
{
return;
}
if (newValue)
{
window.Tag = window.WindowState;
window.Topmost = true;
window.UseNoneWindowStyle = true;
window.IgnoreTaskbarOnMaximize = true;
window.ShowTitleBar = false;
window.ShowCloseButton = false;
window.ShowMaxRestoreButton = false;
window.ShowMinButton = false;
window.WindowStyle = WindowStyle.None;
window.WindowState = WindowState.Maximized;
}
else
{
window.Topmost = false;
window.UseNoneWindowStyle = false;
window.IgnoreTaskbarOnMaximize = false;
window.ShowTitleBar = true;
window.ShowCloseButton = true;
window.ShowMaxRestoreButton = true;
window.ShowMinButton = true;
window.ShowCloseButton = true;
window.ShowMaxRestoreButton = true;
window.WindowStyle = WindowStyle.SingleBorderWindow;
window.WindowState = (WindowState)window.Tag;
}
}
The window gets "sometimes" cut at the border and sometimes it looks right (like in the first picture at the top).
Also I don't know (yet) wheter the space of the title bar is no longer reserved when initially starting with fullscreen (there seems to be a difference, don't know why).
There is a little bug in the current 1.0 release. If you toggle the UseNoneWindowStyle, it doesn't bring back the buttons and toolbar. I'll fix this as soon as possible.
So, here is a little workaround for you.
public static readonly DependencyProperty ToggleFullScreenProperty =
DependencyProperty.Register("ToggleFullScreen",
typeof(bool),
typeof(MainWindow),
new PropertyMetadata(default(bool), ToggleFullScreenPropertyChangedCallback));
private static void ToggleFullScreenPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
var metroWindow = (MetroWindow)dependencyObject;
if (e.OldValue != e.NewValue)
{
var fullScreen = (bool)e.NewValue;
if (fullScreen)
{
metroWindow.UseNoneWindowStyle = true;
metroWindow.IgnoreTaskbarOnMaximize = true;
metroWindow.ShowMinButton = false;
metroWindow.ShowMaxRestoreButton = false;
metroWindow.ShowCloseButton = false;
metroWindow.WindowState = WindowState.Maximized;
}
else
{
metroWindow.UseNoneWindowStyle = false;
metroWindow.ShowTitleBar = true; // <-- this must be set to true
metroWindow.IgnoreTaskbarOnMaximize = false;
metroWindow.ShowMinButton = true;
metroWindow.ShowMaxRestoreButton = true;
metroWindow.ShowCloseButton = true;
metroWindow.WindowState = WindowState.Normal;
}
}
}
public bool ToggleFullScreen
{
get { return (bool)GetValue(ToggleFullScreenProperty); }
set { SetValue(ToggleFullScreenProperty, value); }
}
Hope this helps.

WPF numeric format

I have this XAML for acolumn into DataGrid
<DataGridTemplateColumn Header="% Deduccion Anticipo">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding NumPorcentajeAnticipo, Mode=TwoWay, StringFormat={}{0:00.}%}" Visibility="{Binding Merlin_ConceptosFacturacion.BitOtrosItms_Anticipos,Converter={StaticResource boolToVisibility}}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding NumPorcentajeAnticipo, Mode=TwoWay,StringFormat={}{0:00.}%}" Visibility="{Binding Merlin_ConceptosFacturacion.BitOtrosItms_Anticipos,Converter={StaticResource boolToVisibility}}"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
The Stringformat applys as i expect, but muy problem is the user can fill it with any char alpha, number symbol, how can i do to prevent it, it is posible set an inputmask ?
I'm was trying with another StringFormats but any one of them work as I expect.
UPDATE: The column is currently binded to a Numeric property of my view model.
You can use the KeyDown event of a TextBox to intercept and filter out invalid values. You could even create your own derived TextBox and override OnKeyDown for a better encapsulated solution.
None of the built-in controls have the ability to specify an input mask. But, there are masked input controls out there on the internet for WPF. We are using the Telerik Rad Controls for WPF package and it has such a control. I use it in my application and it works very well.
you can achieve your requirement by using following methods.
Put the masked textbox in CellEditingTemplate and set the mask in that masked textbox.
Create the custom render based on your requirement and bind to the CellEditingTemplate.
After some research found this on another question:
Numeric Data Entry in WPF And #Brian Hinchey answer match with some of my needs.
Just add by myself some Culture validations for decimal numbers plus some editing and validation tools. Hope this help somebody else.
To use it:
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<controls:NumericTextBox DecimalPlaces="2" DecimalSeparator="."/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
If no decimal places or separator are provided, it take CultureInfo.CurrentCulture parms
Here is the final code:
public class NumericTextBox : TextBox
{
#region Formato
private string previousText = "";
private bool ApplyingFormat = false;
private CultureInfo _CI = new CultureInfo(CultureInfo.CurrentCulture.LCID,true);
public CultureInfo CI
{
get { return _CI; }
set { _CI = value; }
}
private int _DecimalPlaces = 0;
/// <summary>
/// Numero de plazas decimales
/// </summary>
public int DecimalPlaces
{
get { return _DecimalPlaces; }
set { _DecimalPlaces = value; _CI.NumberFormat.NumberDecimalDigits = value; }
}
public Decimal DecimalValue = 0;
private string _DecimalSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
public string DecimalSeparator
{
get { return _DecimalSeparator; }
set { _DecimalSeparator = value; _CI.NumberFormat.NumberDecimalSeparator = _DecimalSeparator; }
}
//public string DecimalSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
#endregion
public NumericTextBox()
{
HorizontalContentAlignment = HorizontalAlignment.Right;
DataObject.AddPastingHandler(this, OnPaste);
}
private void OnPaste(object sender, DataObjectPastingEventArgs dataObjectPastingEventArgs)
{
var isText = dataObjectPastingEventArgs.SourceDataObject.GetDataPresent(System.Windows.DataFormats.Text, true);
if (isText)
{
var text = dataObjectPastingEventArgs.SourceDataObject.GetData(DataFormats.Text) as string;
if (IsTextValid(text))
{
return;
}
}
dataObjectPastingEventArgs.CancelCommand();
}
private bool IsTextValid(string enteredText)
{
// If keyboard insert key is in toggled mode, and the actual insert point is Decimalseparator, we must avoid to overwrite it
if (SelectionStart == this.Text.IndexOf(DecimalSeparator)
& System.Windows.Input.Keyboard.GetKeyStates(System.Windows.Input.Key.Insert) == System.Windows.Input.KeyStates.Toggled)
{
SelectionStart += 1;
}
if (!enteredText.All(c => Char.IsNumber(c) || c == DecimalSeparator.ToCharArray()[0] || c == '-'))
{
return false;
}
//We only validation against unselected text since the selected text will be replaced by the entered text
var unselectedText = this.Text.Remove(SelectionStart, SelectionLength);
if ( enteredText == DecimalSeparator && unselectedText.Contains(DecimalSeparator))
{
// Before return false, must move cursor beside Decimal separator
SelectionStart = this.Text.IndexOf(DecimalSeparator) + 1;
return false;
}
if (enteredText == "-" && unselectedText.Length > 0)
{
return false;
}
return true;
}
private bool ApplyFormat(TextChangedEventArgs e)
{
if (!ApplyingFormat)
{
ApplyingFormat = true;
int SelectionStartActual = SelectionStart;
string FinallText = this.Text;
if (!FinallText.Contains(DecimalSeparator) & DecimalPlaces > 0)
{
FinallText = String.Format("{0}{1}{2}", this.Text, DecimalSeparator, new string('0', DecimalPlaces));
}
bool state = Decimal.TryParse(FinallText, NumberStyles.AllowCurrencySymbol | NumberStyles.AllowDecimalPoint | NumberStyles.AllowTrailingSign, _CI, out DecimalValue);
DecimalValue = Math.Round(DecimalValue, DecimalPlaces);
if (DecimalValue == 0)
{
FinallText = "";
}
else
{
if (FinallText != DecimalValue.ToString(_CI))
{
FinallText = DecimalValue.ToString(_CI);
}
}
if (FinallText != this.Text)
{
this.Text = FinallText;
SelectionStart = SelectionStartActual;
}
previousText = this.Text;
ApplyingFormat = false;
return state;
}
else
{
return true;
}
}
protected override void OnTextChanged(TextChangedEventArgs e)
{
e.Handled = !ApplyFormat(e);
base.OnTextChanged(e);
}
protected override void OnPreviewTextInput(System.Windows.Input.TextCompositionEventArgs e)
{
e.Handled = !IsTextValid(e.Text);
base.OnPreviewTextInput(e);
}
}

Categories