How to use an already bound key in the code behind? - c#

I want to use my Tab key to validate the value inserted into a textbox. I also want my Tab key to move on to the next textbox if the validation went well.
So I have my XAML file:
<StackPanel FocusManager.FocusedElement="{Binding ElementName=DVM_Positive_ReadOut}" Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center" Height="400" Width="602" >
<StackPanel Orientation="Horizontal" Margin="5" Height="80">
<Label HorizontalContentAlignment="Left" VerticalAlignment="Center" Padding="5" FontSize="25" Content="DVM Positive Readout" Width="290"/>
<TextBox Style="{StaticResource CodeDigit}" x:Name="DVM_Positive_ReadOut" Width="300" Height="50" IsReadOnly="{Binding Positive_ReadOnly}" Text="{Binding DVM_Pos, UpdateSourceTrigger=PropertyChanged}">
<TextBox.InputBindings>
<KeyBinding Key="Tab" Command="{Binding ValidateReadOnly}" CommandParameter="{Binding ElementName=DVM_Positive_ReadOut}"/>
</TextBox.InputBindings>
</TextBox>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="5" Height="80">
<Label HorizontalContentAlignment="Left" VerticalAlignment="Center" Padding="5" FontSize="25" Content="DVM Negative Readout" Width="290" />
<TextBox Style="{StaticResource CodeDigit}" x:Name="DVM_Negavtive_ReadOut" Width="300" Height="50" IsReadOnly="{Binding Negative_ReadOnly}" Text="{Binding DVM_Neg, UpdateSourceTrigger=PropertyChanged}">
<TextBox.InputBindings>
<KeyBinding Key="Tab" Command="{Binding ValidateReadOnly}" CommandParameter="{Binding ElementName=DVM_Negavtive_ReadOut}"/>
</TextBox.InputBindings>
</TextBox>
</StackPanel>
<StackPanel >
<Button Content="Enter" FontSize="25" Width="300" Height="50" Margin="50">
<Button.InputBindings>
<KeyBinding Key="Return" Command="{Binding ValidateInsert}" CommandParameter="{Binding ElementName=EnterButton}"/>
</Button.InputBindings>
</Button>
<Label HorizontalContentAlignment="Center" VerticalAlignment="Center" Padding="5" FontSize="25" Content="{Binding TestGroupLabel}" Width="290" />
</StackPanel>
</StackPanel>
As you can see at line 7, I bound the Tab key to ValidateReadOnly which is used in my ViewModel.
Now I also want to use my Tab key to switch between textboxes. So I wrote in my code behind file:
private void Window_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space)
{
e.Handled = true;
return;
}
if (e.Key == Key.Tab)
{
TraversalRequest tRequest = new TraversalRequest(FocusNavigationDirection.Next);
UIElement keyboardFocus = Keyboard.FocusedElement as UIElement;
if (keyboardFocus != null)
{
keyboardFocus.MoveFocus(tRequest);
}
e.Handled = true;
}
}
The problem here is that I cannot use my Tab key for the code in my code-behind file because I have bound the Tab key to ValidateReadOnly in my ViewModel.
Yes, I could write the focus code from my code-behind file in my ViewModel with the validation code, but I found it hard to work with focus in the ViewModel.

Related

Getting selected item in ListView without selecting an Item on UI

I'm working on a WPF application where I've made a ListView on UI which is two-way binding enabled. This WPF application is being developed for a windows 10 based smartphone. So whenever a user taps an item in the list whose data source is data-binded to back data collection, I've to do some operation for that item in code behind.
Now the problem is, I always receive a null object from the below function whenever the user taps on the item.
CartItem selectedItem = (CartItem)lv_CartItems.SelectedItem;
I only get a filled item object when the user actually selects an item by clicking on ListViewItem rather than tapping on it.
I want to get the selected item when the user taps on it. Is there any workaround available in WPF this problem? I've stuck here
My ListViewItem template looks like this.
<ListView Name="lv_CartItems" Loaded="lv_CartItems_Loaded"
HorizontalAlignment="Center" ScrollViewer.CanContentScroll="False"
ScrollViewer.VerticalScrollBarVisibility="Visible"
Width="250" Height="230" SelectionMode="Single"
>
<ListView.ItemTemplate>
<DataTemplate>
<Viewbox>
<Grid Width="230" Height="110" >
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width=".1*" />
<ColumnDefinition />
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition Width=".5*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border BorderBrush="LightGray" BorderThickness="1"
Grid.Row="0" Grid.Column="0"
Grid.ColumnSpan="6" Grid.RowSpan="3" >
</Border>
<Viewbox Grid.Row="0" >
<Image Name="img_ItemImage"
Source="{Binding Image, Mode=TwoWay }"
Width="20" Height=" 25" />
</Viewbox>
<Viewbox Grid.Column="2" Grid.ColumnSpan="3" VerticalAlignment="Top" >
<TextBlock Name="lbl_ItemName" TextWrapping="Wrap" Width="180" Foreground="Gray"
Text="{Binding Name , Mode=TwoWay }" >
</TextBlock>
</Viewbox>
<Viewbox Grid.Row="1" Margin="10,0" VerticalAlignment="Top" >
<TextBlock Foreground="Gray" >Qty:</TextBlock>
</Viewbox>
<Viewbox Grid.Row="2" Margin="0,0" VerticalAlignment="Top" >
<StackPanel Orientation="Horizontal" >
<Button Name="btn_Minus" FontWeight="ExtraBold" Tag="{Binding SKU_No,Mode=TwoWay}" Padding="0" Width="12"
Resources="{StaticResource cartitembutton}" Click="btn_Minus_Click" >
<Image Source="/Resources\Icons\minus.png" ></Image>
</Button>
<Border BorderThickness="1" Margin="2,0" Width="13" CornerRadius="2" BorderBrush="LightGray" >
<TextBlock Name="lbl_Quantity" FontWeight="Bold" Foreground="Gray"
HorizontalAlignment="Center" VerticalAlignment="Center"
Text="{Binding Quantity , Mode=TwoWay }" >
</TextBlock>
</Border>
<Button Name="btn_Increment" FontWeight="ExtraBold" Width="12"
Resources="{StaticResource cartitembutton}" Tag="{Binding SKU_No,Mode=TwoWay}"
Padding="0"
Click="btn_Increment_Click">
<Image Source="/Resources\Icons\union_10.png" ></Image>
</Button>
</StackPanel>
</Viewbox>
<Viewbox Grid.Row="1" Grid.Column="2" Margin="5,0"
HorizontalAlignment="Left" Grid.ColumnSpan="3" >
<TextBlock Name="lbl_Price" FontWeight="DemiBold"
Text="{Binding Price , Mode=TwoWay}" ></TextBlock>
</Viewbox>
<Viewbox Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="3"
VerticalAlignment="Top" Margin="0,0" >
<TextBlock Name="lbl_Appearence"
Text="{Binding Appearance , Mode=TwoWay }"
TextWrapping="Wrap" Foreground="Gray" Width="210" >
</TextBlock>
</Viewbox>
<Viewbox Grid.Column="5" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="2,2"
>
<Button Name="btn_DeleteItem"
Click="btn_DeleteItem_Click"
Resources="{StaticResource cartitembutton}" >
<Image Source="/Resources/Icons/delete.png" ></Image>
</Button>
</Viewbox>
</Grid>
</Viewbox>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This is how a listVeiw looks like.
You don't actually want the selected item, you want to know which item contained the button that was clicked- whether that item is selected or not.
You can do this with events, but the more "correct" way to do it in WPF is with commands.
Commands are a pattern which separate the logic of an action (e.g. deleting an item) from the visual component that triggers the action (e.g. the button the user clicks). A command includes a parameter, which you can use to specify which item the command is being executed on. There are a couple different types on commands in WPF, but I'll be explaining using RoutedCommand.
In your case you'd first declare your command(s) in your Window:
public static readonly RoutedCommand DeleteItemCommand =
new RoutedCommand("DeleteItem", typeof(MainWindow));
private void OnCanExecuteDeleteItem(object sender , CanExecuteRoutedEventArgs e)
{
e.CanExecute = e.Parameter != null;
}
private void OnExecuteDeleteItem(object sender, ExecutedRoutedEventArgs e)
{
SomeType item = (SomeType)e.Parameter;
//Actually delete the item
}
And you'd add a CommandBinding to your Window which links the command to the methods which handle it:
<Window.CommandBindings>
<CommandBinding Command="local:MainWindow.DeleteItemCommand" CanExecute="OnCanExecuteDeleteItem" Executed="OnExecuteDeleteItem"/>
</Window.CommandBindings>
And finally, to link your delete Button to the command:
<Button Name="btn_DeleteItem" Resources="{StaticResource cartitembutton}" Command="local:MainWindow.DeleteItemCommand" CommandParameter="{Binding}">
<Image Source="/Resources/Icons/delete.png"/>
</Button>
CommandParameter="{Binding}" works because your Button is inside a DataTemplate, so its DataContext will be the item that is being displayed. This lets you check e.Parameter in your routed event methods to see which item is being interacted with.

Extended Textbox is behind other elements in WPF

It's the first time i am learning WPF with C#.
So i have a textbox which is extended when i click on a button. The problem is when i extend it,it remains behind my other elements(textboxes etc...)
Here is the xml code for the textbox.
<StackPanel Grid.Column="1" Grid.ColumnSpan="4" Grid.Row="3" Grid.RowSpan="5" Panel.ZIndex="0" Visibility="Collapsed" Name="descriptionPanel" Margin="2,0,0,0" Background="White">
<Border BorderBrush="DarkGray" BorderThickness="1" CornerRadius="5">
<StackPanel Orientation="Horizontal">
<TextBox Name="descriptionTextBoxExtended"
Margin="10,10,10,10"
Style="{StaticResource expandedTextBox}"
Text="{Binding Path=Description, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true, TargetNullValue=''}"
IsReadOnly="{Binding RelativeSource={RelativeSource AncestorLevel=1,AncestorType=Control}, Path=SecurityLevel2ReadOnly, Mode=OneWay}"
/>
<Button Name="descriptionHide" Style="{StaticResource MinusButton}" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,10,10" Click="descriptionHide_Click" />
</StackPanel>
</Border>
</StackPanel>
And here is the C#
private void exDescription_Click(object sender, RoutedEventArgs e)
{
descriptionPanel.Visibility = Visibility.Visible;
}
This is how it looks when i run it before i click the extend button:
And this is how it looks when i extend the textbox:
I want all the highlighted components to be behind the textbox.
You should give us the code of the other elements beside "descriptionPanel", but as mm8 pointed out, it seems that your elements are not in the same Panel.

Access PlaceHolderText property of Textbox and set it to initially value once the Page/User Control loads

I am working on a UWP app and I have implemented a UserControl.The user control has multiple Textboxes and the usercontrol has been implemented in a different view page. I want to make sure that whenever the View page loads, all the textboxes have Enteras the default text that goes off when the textbox is highlighted.
My UserControl has this implementation
<UserControl >
---------------------------
----------------------------
<Border Grid.Row="1" Grid.Column="2" BorderBrush="{StaticResource brush}" BorderThickness="0,3,0,0" >
<local:NumericTextBox x:Name="TaxifuelRevised" IsEnabled="{Binding FuelPlanInfo.IsTappable}" Tag="TaxiFuelActual" TextAlignment="Right" Text="{Binding FuelPlanInfo.TaxiFuelActualInPreferredUnit,ElementName=rootFuelControl,Mode=TwoWay,UpdateSourceTrigger=Explicit}"
Margin="0,0,40,0" Style="{StaticResource TransparentTextBox}" HorizontalAlignment="Right" VerticalAlignment="Center" Foreground="#FF0078D7"
BorderBrush="{x:Null}" Background="{x:Null}" FontSize="40" FontFamily="Helvetica" InputScope="Number"
KeyDown="TextBox_KeyDown" MaxLength="5" GotFocus="TextBox_GotFocus" LostFocus="TextBox_LostFocus" Tapped="KeyBoardInputScope_Tapped" />
</Border>
</UserControl>
The view where it has been implemented is
<Pivot x:Name="MyPivot" Grid.Row="1" ManipulationMode="None" Margin="115,10,90,20" SelectionChanged="MyPivot_SelectionChanged" HorizontalAlignment="Stretch" Width="2536" >
<PivotItem Tag="Fuel Plan" Margin="0" ManipulationMode="None">
<PivotItem.Header >
<StackPanel >
<Image Name="FuelPlanImage" Source="ms-appx:///Assets/fuel_plan_icon.png" Width="82" Height="80"></Image>
<TextBlock Margin="0,8,0,0" TextAlignment="Center" Text="Fuel Plan" FontSize="40"/>
</StackPanel>
</PivotItem.Header>
<local:FuelPlan x:Name="FuelPlanUC" HorizontalAlignment="Stretch" FuelPlanInfo="{x:Bind ViewModel.FuelPlanInfo, Mode=OneWay}"></local:FuelPlan>
</PivotItem>
Checkout the PlaceholderText property of the TextBoxControl.

How to use a Popup binded to a ToggleButton inside a ListView in xaml wpf?

I want to make a list of ToggleButtons. Each of them is binded to a popup.
I had a problem with that, so I tried to put everything inside a StackPanel.
But, now, when the app is running, it shows an empty space (for the Popup) right after the ToggleButton. What can I do to solve that?
I've just added two images:
The first one is when the page is being uploaded.
The second one is when I scroll down the page.
<ListView x:Name="ListOfRecipes" HorizontalAlignment="Center" VerticalAlignment="Top" ItemsSource="{Binding}" Grid.Row="1" Margin="25,0.333,25,35" ScrollViewer.VerticalScrollMode="Enabled" Grid.RowSpan="5" >
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<ToggleButton x:Name="RecipeButton" Grid.Row="1" BorderBrush="#FF65C365" VerticalAlignment="Center" HorizontalAlignment="Center" Click="Button_Click" Height="150" Width="328" >
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" Height="128" Width="328">
<Image Source="{Binding Path=ImageUri}" Height="128" Width="128" Margin="0,6,0,-5.667" />
<StackPanel Orientation="Vertical" HorizontalAlignment="Left" VerticalAlignment="Top" Height="128" Width="192">
<TextBlock Height="25" Width="190" Foreground="#FF6FDC13" Text="{Binding Name}" VerticalAlignment="Top" />
<Image Name="YesOrNoImage" Source="{Binding Path=YesOrNoImage}" Width="102" Height="102" HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
</StackPanel>
</StackPanel>
</ToggleButton>
<Popup IsOpen="{Binding IsChecked, ElementName=RecipeButton, Mode=TwoWay}" Height="514" Width="328" VerticalAlignment="Center" Name="PopupOne" Grid.Row="1" Grid.RowSpan="4" IsLightDismissEnabled="True" IsHoldingEnabled="False" ScrollViewer.VerticalScrollMode="Enabled" >
<Border BorderBrush="#FF65C365" BorderThickness="1" Background="White" Height="514" Width="328">
<StackPanel Orientation="Vertical" ScrollViewer.VerticalScrollMode="Enabled">
<Image Source="{Binding Path=ImageUri}" Height="328" Width="328" />
<TextBlock Foreground="#FF6FDC13" Text="{Binding Name}" HorizontalAlignment="Left" FontSize="28" />
<ScrollViewer VerticalScrollMode="Enabled" >
<TextBlock Foreground="Black" Text="{Binding RecipeText}" HorizontalAlignment="Left" FontSize="18" />
</ScrollViewer>
</StackPanel>
</Border>
</Popup>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
It seems that the issue is caused by the <PopUp Height=514/>
To test it, set the height to 0 to see if it fixes the gap. If so, you can bind the visibility to PopUp.IsOpen using a Visibility converter (I think Blue MVVM has one). Since I'm not very educated on Converters at the moment, I came up with a workaround.
public RecipeButton : INotifyPropertyChanged {
// Need to implement INotifyPropertyChanged logic on IsCheckedVisiblity for UI to be notified of visibility changes
public Visibility IsCheckedVisibility { get; set; }
private bool _IsChecked;
public bool IsChecked {
get { return _IsChecked };
set { _IsChecked = value;
this.IsCheckedVisibility = value == true ? Visiblity.Collapsed : Visiblity.Visible;
}
}
<PopUp Visibility = "{Binding IsCheckedVisibility}"/>
Let me know if that doesn't work and I'll try something else.

FlyOut on DataTemplate error WP 8.1

I have a DataTemplate for the ListBox Items. I would like that when the user holds a listbox item, a open Attached Flyout appears upon the item with some options. So when I hold an item of the listbox, in debug mode, I enter the method but it crashes telling me that there's no flyoutBase attached to that element, but there is... As I use a Custom DataTemplateSelector, the DataTemplate is written in the App.xaml as a resource. This is my DataTemplate for the ListBoxItem:
<DataTemplate x:Key="FollowerOuterTemplate">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch" >
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch" Name="FollowersList">
<FlyoutBase.AttachedFlyout>
<MenuFlyout>
<MenuFlyoutItem Text="Delete" />
<MenuFlyoutItem Text="Refresh" />
<MenuFlyoutItem Text="Share" />
</MenuFlyout>
</FlyoutBase.AttachedFlyout>
<StackPanel Orientation="Vertical" Width="282">
<TextBlock Grid.Row="0" FontSize="33" Text="{Binding Pseudo}" Foreground="Gray" Height="46" Margin="0,0,-0.333,0"/>
<TextBlock Grid.Row="1" FontSize="20" Text="{Binding NomPrenom}" Foreground="#5bc5eb" Height="27" Margin="0,0,-0.333,0"/>
<TextBlock Grid.Row="2" FontSize="20" Text="Restez appuyer pour bloquer" Foreground="#BCC6CC" Height="27" Margin="0,0,-0.333,0"/>
</StackPanel>
<StackPanel Orientation="Vertical" HorizontalAlignment="Stretch" Width="113">
<Image Name="StatutContact" Height="43" Source="/Ressources/Images/checkedTests2.png" Stretch="Fill" Margin="0,20,0,0" Width="44" HorizontalAlignment="Center"/>
</StackPanel>
</StackPanel>
</StackPanel>
</DataTemplate>
And here is my called method:
private void FollowersList_Holding(object sender, HoldingRoutedEventArgs e)
{
try
{
FrameworkElement senderElement = sender as FrameworkElement;
FrameworkElement element = sender as FrameworkElement;
if (element == null) return;
// If the menu was attached properly, we just need to call this handy method
FlyoutBase.ShowAttachedFlyout(element);
}
catch (Exception ex)
{
}
}
The exact error is : System.ArgumentException: The parameter is incorrect.
ShowAttached was called on an element without an attached FlyoutBase

Categories