Extended Textbox is behind other elements in WPF - c#

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.

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.

WPF TextBox does not lose focus

I knwow there are many other who wrote about this but the suggested solutions don't solve my problem.
I've got a sort of gallery and I need that when the user edits the number specified in the TextBox automatically the image is updated.
Initially I tried with LostFocus event, but it doesn't always fire as explained here.
If I bind the property as suggested here, I have too many events if the number has more than one digit.
Then I tried to do this, but it doesn't work.
This is how my TextBox is defined:
<TextBox Margin="2" Text="{Binding NImageShown}" FontSize="18"
LostFocus="ImageIndex_OnLostFocus"
Name="ImageIndex" Height="40" Width="60"
VerticalAlignment="Center" VerticalContentAlignment="Center"
Focusable="True">
</TextBox>
I implemented the third solution by attaching the window to MouseDown event:
<Window x:Class="...."
.....
MouseDown="Window_MouseDown"....>
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (ImageIndex.IsFocused)
Keyboard.ClearFocus();
}
With this solution I sawy that ImageIndex.IsFocused remains true even after Keyboard.ClearFocus(): this is the reason why I think that solution does not fix my problem.
Any help is really appreciate!
EDIT
Changes based on the suggestions:
<Grid Grid.Row="2" Grid.Column="2" Name="GridTextbox">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
.....
<StackPanel Grid.Column="2" Orientation="Horizontal"
HorizontalAlignment="Right">
<TextBox Margin="2" Text="{Binding NImageShown}" FontSize="18" LostFocus="ImageIndex_OnLostFocus"
Name="ImageIndex" Height="40" Width="60" VerticalAlignment="Center" VerticalContentAlignment="Center" Focusable="True"></TextBox>
<Label Style="{DynamicResource LabelStyle}" VerticalAlignment="Center"
Content="{Binding NTotalImages}" FontSize="18" Padding="5,0,5,0" Margin="5,5,5,5" />
</StackPanel>
</Grid>
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (ImageIndex.IsFocused)
{
GridTextbox.Focus();
Keyboard.ClearFocus();
}
}
Even with these changes, LostFocus doesn't fire.
SOLUTION
Change the xaml as suggested in this way and keep the code behind as written before:
<TextBox Margin="2" Text="{Binding NImageShown}" FontSize="18"
LostKeyboardFocus="ImageIndex_OnLostFocus"
KeyDown="ImageIndex_OnLostFocus"
Name="ImageIndex" Height="40" Width="60"
VerticalAlignment="Center" VerticalContentAlignment="Center"
Focusable="True">
</TextBox>

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.

How to change GridView.ItemTemplate while app is running?

In my app I have page with GridView and ComboBox. I want to change GridView.ItemTemplate property according to selected item in ComboBox. How should I implement it?
btw, I know about this question, but it is quite old and it does not look like "best practice". (How visibility/invisibility of ui control affects cpu/gpu load?)
My GridView:
<GridView x:Name="gridViewMain" Grid.Row="1" SelectionMode="None" IsItemClickEnabled="True"
ItemsSource="{Binding CurrentList}" ItemTemplate="{StaticResource gridViewMainItemTemplate}"
Loaded="gridViewMain_Loaded" LayoutUpdated="gridViewMain_LayoutUpdated">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ItemClick">
<core:CallMethodAction MethodName="GridViewClick"
TargetObject="{Binding Mode=OneWay}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</GridView>
One of my templates:
<DataTemplate x:Key="gridViewMainItemTemplate">
<Grid x:Name="gridATemplate" Width="185" Height="288">
<Image x:Name="imgATemplate" Source="{Binding image_url}" Stretch="UniformToFill"
HorizontalAlignment="Center" VerticalAlignment="Center" />
<Grid Background="{ThemeResource ListViewItemOverlayBackgroundThemeBrush}" VerticalAlignment="Bottom">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock x:Name="textBlockTitle" Text="{Binding title}"
TextWrapping="Wrap" Style="{StaticResource BodyTextBlockStyle}" Margin="5,0,0,0"
Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Foreground="White" FontWeight="Bold"
MaxHeight="50" />
<TextBlock x:Name="textBlockType" TextWrapping="Wrap" Style="{StaticResource BodyTextBlockStyle}"
Margin="5,0,0,0"
Grid.Column="0" Grid.Row="1" Foreground="White" Text="{Binding type}" FontWeight="Bold" />
<StackPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal">
<TextBlock x:Name="textBlockProgressL" TextWrapping="Wrap"
Style="{StaticResource BodyTextBlockStyle}" FontWeight="Bold" Foreground="White"
Text="Progress:" />
<TextBlock x:Name="textBlockProgressV" TextWrapping="Wrap"
Style="{StaticResource BodyTextBlockStyle}" FontWeight="Bold" Foreground="White"
Text="{Binding watched_episodes}" Margin="10,0,0,10" />
</StackPanel>
</Grid>
</Grid>
</DataTemplate>
Sure you can do this! In XAML you can do anything. What you cannot do is change the Template on the fly without re-rendering. Remember, this is like telling your printer to use card stock. It will obey. If you change the setting to use notebook paper, it will obey that, too. You will just have to print again since it has already printed on card stock.
There are a few ways for you to re-render a GridView. One way is to navigate away from the page and navigate back. That's not ideal sounding in your scenario. Odds are, in your scenario, you just need to reset the ObservableCollection you are using. Like this:
void Reset<T>(ObservableCollection<T> collection)
{
var original = collection.ToArray();
collection.Clear();
foreach (var item in original)
collection.Add(item);
}
Best of luck!
You'll want to use datatemplateselector
http://blogs.msdn.com/b/bryanbolling/archive/2012/12/08/how-to-control-the-datatemplateselector-in-windows-store-apps.aspx
You can create multiple itemtemplates and choose which one to display based on any condition.
You'll have to refresh the gridview whenever the selection changes.

Categories