C# WPF popup doesn't appear - c#

I'm fairly new at coding and i'm struggling with a popup that doesn't appear at runtime.
I'm trying to make an autocomplete/suggestion popup list but i can't seem to be able to make it work.
Here's my XAML:
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="130"/>
<ColumnDefinition x:Name="editorInputColumn"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Ajouter (séparateur ';') :">
<TextBlock.Foreground>
<SolidColorBrush Color="{DynamicResource FontColor}"/>
</TextBlock.Foreground>
</TextBlock>
<Grid x:Name="popupEditorGrid" Grid.Column="1" Visibility="Visible">
<Popup Placement="Top" Visibility="Visible" StaysOpen="True" Panel.ZIndex="1000" x:Name="EditorPopup" Grid.Column="1" Width="{Binding Path=ActualWidth, ElementName=editorInputColumn}">
<StackPanel x:Name="EditorPopupStackPanel">
<StackPanel.Background>
<SolidColorBrush Color="{DynamicResource EllipseSecondary}"/>
</StackPanel.Background>
<TextBlock Text="test"/><!--this is just an attempt at displaying something in the popup, but even this does not appear at runtime-->
</StackPanel>
</Popup>
</Grid>
<TextBox Grid.Column="1" KeyUp="editorAddInput_KeyUp" x:Name="editorAddInput" >
<TextBox.BorderBrush>
<SolidColorBrush Color="{DynamicResource BoutonMarge}"/>
</TextBox.BorderBrush>
</TextBox>
</Grid>
and here's the code behind:
private void editorAddInput_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
string lastInput;
List<string> inputList = editorAddInput.Text.ToUpper().Split(',', ';').ToList();
if (inputList.Count != 0)
{
lastInput = inputList[inputList.Count - 1];
}
else
{
lastInput = editorAddInput.Text;
}
List<Editor> matchingEditorsList = new List<Editor>();
EditorPopupStackPanel.Children.Clear();
foreach(Editor editor in localEditorsList)//look up among all known names
{
if(editor.Name.StartsWith(lastInput))
{
matchingEditorsList.Add(editor);
}
}
if(matchingEditorsList.Count!=0)
{
EditorPopup.Visibility = Visibility.Visible;
foreach(Editor editor in matchingEditorsList)
{
EditorPopupStackPanel.Children.Add(new TextBlock() { Text = editor.Name });
}
EditorPopup.StaysOpen = true;
EditorPopup.IsOpen = true;
}
else
{
EditorPopup.Visibility = Visibility.Collapsed;
EditorPopup.IsOpen = false;
}
}
The input Textbox is supposed to be able to get several names, separated by a ";", so I start by getting the last one being typed.
Funny enough, the popup does appear in Visual Studio's Conceptor view when selected, but not when running. I've tried playing with z-index with no success. Any idea on what i messed up?

Put textbox inside grid in XAML

You are missing the IsOpen property, which should be set to true for the popup to be displayed.

Related

WPF: How to autoreset/autorefresh the textbox after scanning barcode in WPF?

I'm making a simple WPF program where the user will basically only need to scan the barcode using a USB barcode scanner and the program will send the data straight to the cloud ERP. Right now, the program works, but the user has to manually click the textbox after scanning, clear the data and scan again. I just want the user to open the software and just keep on scanning using his barcode reader without having to manually erase the textbox data. How can I do that?
<Window x:Class="ProductionScanner.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModel="clr-namespace:ProductionScanner.MVVM.ViewModel"
xmlns:local="clr-namespace:ProductionScanner"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800"
Background="#181735" >
<Window.DataContext>
<viewModel:ReceiptViewModel />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid Background="#0F0F2D"
Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="Foods"
Foreground="White"
Grid.Column="1"
VerticalAlignment="Center"
HorizontalAlignment="Left"
/>
<TextBlock Text="Records"
Foreground="White"
Grid.Column="2"
VerticalAlignment="Center"
HorizontalAlignment="Center"
/>
</Grid>
<StackPanel FocusManager.FocusedElement="{Binding ElementName=txtIniFocus}">
<TextBox x:Name="txtIniFocus" Margin="6" Text="{Binding Barcode, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" TextWrapping="Wrap" VerticalAlignment="Top" Width="150" Grid.Row="1" TextChanged="TextBox_TextChanged">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding ReceiptCommand}" />
</TextBox.InputBindings>
</TextBox>
</StackPanel>
</Grid>
And, the ReceiptViewModel.cs:
using ProductionScanner.Cores;
using ProductionScanner.MVVM.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Windows;
using System.Windows.Controls.Primitives;
namespace ProductionScanner.MVVM.ViewModel
{
public class ReceiptViewModel: ObservableObject
{
private string _barcode;
public string Barcode
{
get { return _barcode; }
set { _barcode = value; OnPropertyChanged(); }
}
public RelayCommand ReceiptCommand { get; set; }
public ReceiptViewModel()
{
ReceiptCommand = new RelayCommand(x =>
{
receiptInventory();
});
}
private void receiptInventory()
{
if (Barcode.Length == 12)
{
var inventoryIDFrom = Barcode.Substring(0, 6);
var kgIntFrom = Barcode.Substring(6);
var kgDecimalFrom = kgIntFrom.Substring(0,kgIntFrom.Length-4) + "." + kgIntFrom.Substring(kgIntFrom.Length - 4, 3);
ERPRestService _erpRestService = new ERPRestService();
ReceiptItems receiptItems = new ReceiptItems();
receiptItems.InventoryID = inventoryIDFrom;
receiptItems.Qty = Convert.ToDecimal(kgDecimalFrom);
receiptItems.WarehouseID = "WH001";
receiptItems.LocationID = "L001";
receiptItems.LotSerialNbr = "";
receiptItems.ExpirationDate = DateTime.Now;
try
{
var jsonObj1 = new
{
Description = new
{
value = "Receipt"
},
Hold = new
{
value = false
},
Details = new[]
{
new {
InventoryID = new
{
value = receiptItems.InventoryID
},
Qty = new
{
value = receiptItems.Qty
},
WarehouseID = new
{
value = receiptItems.WarehouseID
},
Location = new
{
value = receiptItems.LocationID
}
}
}
};
string entityAsString = JsonConvert.SerializeObject(jsonObj1);
//string parameters1 = "$expand=Details";
var receipt = _erpRestService.Put("InventoryReceipt", null, entityAsString);
string refRelease = JObject.Parse(receipt)["ReferenceNbr"]["value"].ToString();
var release = new
{
entity = new
{
ReferenceNbr = new
{
value = refRelease
}
}
};
string jsonRelease = JsonConvert.SerializeObject(release);
jsonRelease = _erpRestService.Post("InventoryReceipt", "ReleaseInventoryReceipt", jsonRelease);
MessageBox.Show("Your AR Confirm has completed.", "Confirm", MessageBoxButton.OK, MessageBoxImage.Information);
}
catch (Exception ex)
{
throw (ex);
}
finally
{
_erpRestService.Dispose();
}
}
}
}
}
I tried a simplified version of the markup and code.
The messagebox looked a bit suspicious to me as I was thinking it might take focus. What might happen after that.
Use of return was also a concern as I wondered what else return might do.
There's nowhere else for the focus to go.
If I just press tab then the cursor is still in the textbox.
My experimental markup:
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid Background="#0F0F2D"
Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="Foods"
Foreground="White"
Grid.Column="1"
VerticalAlignment="Center"
HorizontalAlignment="Left"
/>
<TextBlock Text="Records"
Foreground="White"
Grid.Column="2"
VerticalAlignment="Center"
HorizontalAlignment="Center"
/>
</Grid>
<StackPanel FocusManager.FocusedElement="{Binding ElementName=txtIniFocus}">
<TextBox x:Name="txtIniFocus" Margin="6" Text="{Binding Barcode, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" TextWrapping="Wrap" VerticalAlignment="Top" Width="150" Grid.Row="1">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding ReceiptCommand}" />
</TextBox.InputBindings>
</TextBox>
</StackPanel>
</Grid>
</Window>
My viewmodel
public partial class MainWindowViewModel : ObservableObject
{
[ObservableProperty]
private string barcode = "65765765";
[RelayCommand]
private async Task Receipt()
{
// Your receipt processing would go here
MessageBox.Show("Your AR Confirm has completed.", "Confirm", MessageBoxButton.OK, MessageBoxImage.Information);
Barcode=string.Empty;
}
}
I hit enter, the messagebox shows. I click OK. The messagebox closes, textbox is empty and the cursor is in the textbox.
If what you've shown us was all you have then I think setting Barcode to string.Empty would probably work.
Not sure it'd make much difference but my property changed notification is from the community toolkit mvvm and using the code generator. It will check for equality before raising property changed.
I'm not sure what your observableobject is there.
I still think the messagebox is a bad idea as the user has to pick the mouse up and click. An on screen indicator would be something to consider instead.
FWIW
I would also recommend just checking the length is 12 and drive the processing that way.
If you do both then the user could just scan, the receipt is done, scan the next receipt is done, scan....
They wouldn't have to touch keyboard or mouse.
That's the approach I've used for warehouse and product scanning on what sound like similar apps.

UWP Object reference not set to an instance of an object when adding item to Azure easy table

I have a popup window that takes in input from a user and then should send it to a model which then POSTS it to an azure easy table. When I build the project everything runs fine until I hit the submit button then the app crashes and I get the Null Exception Object reference not set to an instance of an object.
XAML for input:
<Popup x:Name="ppup" IsOpen="False" IsLightDismissEnabled="True"
Width="320" HorizontalAlignment="Left">
<Popup.ChildTransitions>
<TransitionCollection>
<!--<EdgeUIThemeTransition Edge="Left" />-->
<PaneThemeTransition Edge="Left" />
</TransitionCollection>
</Popup.ChildTransitions>
<Grid Width="380" Height="{Binding ElementName=flyoutPane, Path=Height}" Background="{ThemeResource FlyoutBackgroundThemeBrush}" >
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10,10,10,10" >
<TextBlock Name="NameText" Text="Enter Name:"/>
<TextBox Name="NameBox" Width="200" Height="50"/>
<TextBlock Name="SetsText" Text="Enter Sets:"/>
<TextBox Name="SetsBox" Width="200" Height="50"/>
<TextBlock Name="TimeText" Text="Enter Time to complete:"/>
<TextBox Name="TimeBox" Width="200" Height="50"/>
<Button Name="SubmitBtn" Height="30" Width="100" Content="Submit" Click="SubmitBtn_Click"/>
</StackPanel>
</Grid>
</Popup>
C# for handling input and passing it to model:
CombatTableView ctv = new CombatTableView();
private async void SubmitBtn_Click(object sender, RoutedEventArgs e)
{
DrillItem drillItem = new DrillItem();
String Name = NameBox.Text;
int Sets = Int32.Parse(SetsBox.Text);
int Time = Int32.Parse(TimeBox.Text);
await ctv.combatDrillsTable.AddDrill(drillItem, Name, Sets, Time, parameters);
ppup.IsOpen = false;
var dialog = new MessageDialog("Your message here");
await dialog.ShowAsync();
}
View Model:
class CombatTableView
{
public CombatDrillsTable combatDrillsTable { get; set; }
public CombatTableView()
{
this.combatDrillsTable = new CombatDrillsTable();
}
}
Model for interacting with database:
public async Task AddDrill(DrillItem drillItem, String n, int s, int t, string sty)
{
drillItem.Name = n;
drillItem.Sets = s;
drillItem.SetTime = t;
drillItem.Style = sty;
await App.MobileService.GetTable<DrillItem>().InsertAsync(drillItem);
drills.Add(drillItem);
}
In my case the problem was due to a checkbox accidentally bound to the event instead of the property:
<CheckBox x:Name="chkIsActive" Checked="{Binding IsActive}" />
instead of
<CheckBox x:Name="chkIsActive" IsChecked="{Binding IsActive}" />
There was a null value inside combatDrillsTable and the list that was to hold the objects null too because i hadn't put anything into my easy table at that stage so it was throwing a null exception.

Unknown space while highlighting part of text in a texblock (WPF)

From trial and error I managed to highlight part of text in a textblock which is in a datatemplate of a listbox bounded to a property of a custom class. But the problem now is that when highlighting the text i get a weird unknown space between the highlighted text and the rest of the text.
Here is part of the XAML
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox Name="textBox1" TextChanged="textBox1_TextChanged"/>
<ListBox Grid.Row="1" Name="listBox1">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Name="gridOfListbox" Height="25" Margin="0,2">
<DockPanel Name="dockpanelWithTxtBlock">
<TextBlock Name="textbloxk" DockPanel.Dock="Left" FontSize="15" TextAlignment="Center">
<Run Background="Yellow" Text=""></Run>
<Run Text="{Binding ProductID}"></Run>
</TextBlock>
</DockPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
And here part of the code used
ObservableCollection<TItem> items = new ObservableCollection<TItem>();
TItem[] source = new TItem[] { new TItem("Hello"), new TItem("World"), new TItem("System"), new TItem("SystemDefault"), new TItem("SystemFolder") };
And the method for event changedtext
private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
{
string match = textBox1.Text;
foreach (TItem TItem in listBox1.Items)
{
ListBoxItem lbi = (ListBoxItem)this.listBox1.ItemContainerGenerator.ContainerFromItem(TItem);
TextBlock txtBlck = FindFirstElementInVisualTree<TextBlock>(lbi);
Run bold = (Run)txtBlck.Inlines.FirstInline;
Run normal = (Run)txtBlck.Inlines.LastInline;
string s = bold.Text + normal.Text;
if (s.ToLower().StartsWith(match.ToLower()))
{
bold.Text = s.Substring(0, match.Length);
normal.Text = s.Substring(match.Length);
}
else
{
bold.Text = "";
normal.Text = s;
}
}
}
FindFirstElementInVisualTree method is used to find the textboxes needed to search of.
If anymore code is needed let me know.
I also added an image to demonstrate what the problem is.
An help will be appreciated!
Link for image: http://i.stack.imgur.com/rOj0m.png
When you use Run within a TextBlock in XAML, everything not wrapped in <> are considered actual strings. Having a line break would mean a space. Put the two Runs within the same line (without a space in between too).
<TextBlock Name="textbloxk" DockPanel.Dock="Left" FontSize="15" TextAlignment="Center">
<Run Background="Yellow" Text="" /><Run Text="{Binding ProductID}" />
</TextBlock>
Edit
By the way, I just saw your first question which was marked as duplicate. This question is asked correctly; so you should ask questions in this manner in the future.

WPF - MouseMove on image contained in Popup

I made a color-picker with one image(HUE color) and a slider (brightness level).
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.8*"/>
<ColumnDefinition Width="0.2*"/>
</Grid.ColumnDefinitions>
<Border x:Name="borderColorChart" Grid.Column="0">
<Grid>
<Image Stretch="Fill" Source="Assets/colorChart.PNG" MouseDown="Image_MouseDown" MouseMove="Image_MouseMove"/>
<Ellipse x:Name="colorMarker" Width="5" Height="5" StrokeThickness="1" Stroke="#FF0B0B0B"/>
</Grid>
</Border>
<Border x:Name="brightnessSliderBorder" Background="{DynamicResource BrightnessGradient}" Grid.Column="1">
<Grid>
<Slider x:Name="brightnessSlider" Orientation="Vertical" IsMoveToPointEnabled="True" Focusable="False" Minimum="0.0" Maximum="1.0" Style="{DynamicResource SliderStyle}" />
</Grid>
</Border>
</Grid>
This color-picker is contained in a Popup which open when I click on a toggle button :
<ToggleButton x:Name="SelectColorChannel1" Grid.Row="0" Background="{Binding SelectedCurrentColor, ElementName=Channel1Color}">
<Popup IsOpen="{Binding IsChecked, ElementName=SelectColorChannel1}" StaysOpen="True">
<CMiX:ColorPicker x:Name="Channel1Color"/>
</Popup>
</ToggleButton>
Here is the code for the mousemove :
private void Image_MouseDown(object sender, MouseButtonEventArgs e)
{
var cb = new CroppedBitmap((BitmapSource)(((Image)e.Source).Source), new Int32Rect((int)Mouse.GetPosition(e.Source as Image).X, (int)Mouse.GetPosition(e.Source as Image).Y, 1, 1));
_pixels = new byte[4];
cb.CopyPixels(_pixels, 4, 0);
UpdateCurrentColor();
UpdateMarkerPosition();
UpdateSlider();
}
private void Image_MouseMove(object sender, MouseEventArgs e)
{
if (Mouse.LeftButton == MouseButtonState.Pressed)
{
if (e.Source.GetType().Equals(typeof(Image)))
{
var cb = new CroppedBitmap((BitmapSource)(((Image)e.Source).Source), new Int32Rect((int)Mouse.GetPosition(e.Source as Image).X, (int)Mouse.GetPosition(e.Source as Image).Y, 1, 1));
_pixels = new byte[4];
cb.CopyPixels(_pixels, 4, 0);
UpdateMarkerPosition();
UpdateCurrentColor();
Mouse.Synchronize();
UpdateSlider();
}
}
}
And here is the function to update the marker position
private void UpdateMarkerPosition()
{
_markerTransform.X = Mouse.GetPosition(borderColorChart).X - (borderColorChart.ActualWidth / 2);
_markerTransform.Y = Mouse.GetPosition(borderColorChart).Y - (borderColorChart.ActualHeight / 2);
}
The problem is, I can't slide the marker on the image, I can only "click" once to move it, this problem doesn't happen if the color-picker is contained in a ContextMenu. But I need popup, so it stays open while finding the right color on the image and while using the slider.
Any hint ? Thank you
EDIT 1 ---
I have done some testing and now as far as I understand the function UpdateMarkerPosition() on MouseMove is not working when I use a popup, but it is working in case I use a contextmenu... Still, UpdateMarkerPosition() is working on MouseDown
EDIT 2 ---
Ok so now I know precisely that this condition :
if (Mouse.LeftButton == MouseButtonState.Pressed)
is never true in case I use wpf Popup
Take out Popup control from within ToggleButton. And place it separately outside with its Placement property set to Mouse.

Mousemoving Usercontrol in canvas WPF

So, my problem is that i'm trying to move some usercontrols around in a canvas.
This actually works very well, as long as the mousepointer is inside the dockpanel, which is what the usercontrol is made of. However, inside the dockpanel, there are several itemscontrols, and if I click on those, and try to move it, an exception is generated, stating something like "Unable to cast object of type "System.String" to type "UMLDesigner.Model.Node".
This makes sense, but is there a way to get the DockPanel, instead of the Itemscontrol, even though it is the itemscontrol that is clicked?
There is the relevant C# code:
public void MouseMoveNode(MouseEventArgs e)
{
//Is the mouse captured?
if (Mouse.Captured != null)
{
FrameworkElement movingClass = (FrameworkElement)e.MouseDevice.Target;
Node movingNode = (Node)movingClass.DataContext;
Canvas canvas = FindParent<Canvas>(movingClass);
Point mousePosition = Mouse.GetPosition(canvas);
if (moveNodePoint == default(Point)) moveNodePoint = mousePosition;
movingNode.X = (int)mousePosition.X;
movingNode.Y = (int)mousePosition.Y;
}
}
public void MouseUpNode(MouseEventArgs e)
{
//Used to move node
FrameworkElement movingClass = (FrameworkElement)e.MouseDevice.Target;
Node movingNode = (Node)movingClass.DataContext;
Canvas canvas = FindParent<Canvas>(movingClass);
Point mousePosition = Mouse.GetPosition(canvas);
new MoveNodeCommand(movingNode, (int)mousePosition.X, (int)mousePosition.Y, (int)moveNodePoint.X, (int)moveNodePoint.Y);
moveNodePoint = new Point();
e.MouseDevice.Target.ReleaseMouseCapture();
}
And the xaml for some of the usercontrol:
<DockPanel.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0.0">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Azure" Offset="0"/>
<GradientStop Color="Transparent" Offset="1"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DockPanel.Background>
<TextBox Text="{Binding ClassName}" HorizontalAlignment="Center" DockPanel.Dock="Top" Margin="5,0,5,0"/>
<!--Note the " : " is acutally being written to the GUI-->
<ItemsControl Name="attributeList" ItemsSource="{Binding Attributes}" Margin="5,0,5,0" DockPanel.Dock="Top">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock><Run Text="{Binding Path=.}"/> : <Run Text="Type her"/></TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl Name="propertiesList" ItemsSource="{Binding Properties}" Margin="5,0,5,0" DockPanel.Dock="Top">
</ItemsControl>
<ItemsControl Name="methodsList" ItemsSource="{Binding Methods}" Margin="5,0,5,0" DockPanel.Dock="Top">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock><Run Text="{Binding Path=.}"/>() : <Run Text="Type her"/></TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DockPanel>
I would of course also like to know if there is a smarter or better way of doing this.
Add IsHitTestVisible="False" to ItemsControl.

Categories

Resources