WPF NavigationService is null - c#

I'm learning WPF (moving from Procedural PHP) and have written the following to navigate from 'MainWindow' to 'Page1', where there are no errors with the login credentials, but the local variable 'nav' is always null (hence displaying an error message):
namespace YM_POS_20160229_0949
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public void ClickLoginSubmitButton(object sender, RoutedEventArgs e)
{
// Dictionary object is c# equivalent of PHP's 'array["key"] = "value"'
Dictionary<string, string> errMsg = new Dictionary<string, string>();
// declare variables
string varUserName;
string varUserPass;
// define the variables whilst trimming the values passed
varUserName = LoginUsername.Text.Trim();
varUserPass = LoginPassword.Password.Trim();
// ensure something has been submitted & perform validation on the values submitted
// if there are no errors, navigate to the users dashboard (aka Page1)
NavigationService nav = NavigationService.GetNavigationService(new Page1());
// check if the nav variable is populated
if (nav != null)
{
nav.Navigate(nav);
}
else
{
// display an error message to the user advising them an error has occurred and Page1 is not available
MessageBox.Show("An error has occured. unable to proceed to " + nav);
}
}
}
}
Any help greatly appreciated.
Thanks
Newbie Matt
//UI / XAML
<Window x:Class="YM_POS_20160229_0949.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:local="clr-namespace:YM_POS_20160229_0949"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<DockPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="123*"/>
<ColumnDefinition Width="394*"/>
</Grid.ColumnDefinitions>
<TextBox x:Name="LoginUsername" HorizontalAlignment="Left" Height="23" Margin="56.649,55,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" Grid.Column="1"/>
<PasswordBox x:Name="LoginPassword" HorizontalAlignment="Left" Height="23" Margin="56.649,100,0,0" Password="Password" VerticalAlignment="Top" Width="120" Grid.Column="1" />
<Button x:Name="LoginSubmitButton" Content="Submit" HorizontalAlignment="Left" Margin="81.649,172,0,0" VerticalAlignment="Top" Width="75" Click="ClickLoginSubmitButton" Grid.Column="1"/>
</Grid>
</DockPanel>
</Window>

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.

How to get C# WPF MVVM Screensaver use dual monitor?

I am looking for an answer howto get a C#-WPF-MVVM-Screensaver-View on dual and more monitors running. I read several tutorials on webpages and answers here. However, never the coding samples worked on wpf.
Have someone a code exmple that works for wpf and Model View ViewModel Pattern?
I appreciate your help and thank you.
Thanks. I did it on Windows 10.
Create new WPF Window project for C#
Remove the startupuri / startuplocation from app.xaml.
Add a startup method to app.xaml.
4.
<Application x:Class="SeveralDisplays.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SeveralDisplays"
Startup="OnStartup">
<Application.Resources>
</Application.Resources>
</Application>
using System.Drawing;
using System.Windows;
using System.Windows.Forms;
using Application = System.Windows.Application;
namespace SeveralDisplays
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
private void OnStartup(object sender, StartupEventArgs e)
{
Window mainWindow1 = new MainWindow();
Window mainWindow2 = new MainWindow2();
Screen s1 = Screen.AllScreens[0];
Screen s2 = Screen.AllScreens[1];
Rectangle r1 = s1.WorkingArea;
Rectangle r2 = s2.WorkingArea;
mainWindow1.Top = r1.Top;
mainWindow1.Left = r1.Left;
mainWindow2.Top = r2.Top;
mainWindow2.Left = r2.Left;
mainWindow1.Show();
mainWindow2.Show();
mainWindow2.Owner = mainWindow1;
}
}
}
add two classes and ensure they are window-classes.
First / Main view, do not change here too much
<Window x:Class="SeveralDisplays.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:local="clr-namespace:SeveralDisplays"
mc:Ignorable="d"
Loaded="MainWindow_OnLoaded"
Title="MainWindow" Height="350" Width="525">
<Grid>
</Grid>
</Window>
first window code behind
using System.Windows;
namespace SeveralDisplays
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
WindowState = WindowState.Maximized;
WindowStyle = WindowStyle.None;
ShowInTaskbar = false;
}
}
}
Second xaml as window
<Window x:Class="SeveralDisplays.MainWindow2"
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:local="clr-namespace:SeveralDisplays"
mc:Ignorable="d"
Title="MainWindow2"
WindowStartupLocation="Manual"
WindowStyle="None"
WindowState="Maximized"
Height="300" Width="300">
<Grid>
</Grid>
</Window>
Code behind:
using System.Windows;
namespace SeveralDisplays
{
public partial class MainWindow2 : Window
{
public MainWindow2()
{
InitializeComponent();
}
}
}
you can do this simplified and smart. I use only a method inside app.xaml.cs
/// <summary>
/// Shows the screensaver on every monitor. This is a multi monitor
/// application.
/// </summary>
private void ShowScreenSaver()
{
ClockWindow ownerWindow = null;
// Creates window on other screens.
foreach (System.Windows.Forms.Screen screen in System.Windows.Forms.Screen.AllScreens)
{
ClockWindow window = new ClockWindow(screen.Bounds.Width,
screen.Bounds.Height);
// Primary screen does not have WindowsStartupLocation.
if (screen.Primary)
{
// Maximizes screen.
window.WindowState = WindowState.Maximized;
ownerWindow = window;
}
else
{
// Other screens need a WindowStartupLocation on manual.
window.WindowStartupLocation = WindowStartupLocation.Manual;
System.Drawing.Rectangle location = screen.Bounds;
window.Top = location.Top;
window.Left = location.Left - 480;
window.Width = location.Width;
window.Height = location.Height;
}
window.Show();
}
// Sets every other screen owned to prmary window.
// It closes all windows at once.
foreach (Window window in Current.Windows)
{
if (window != ownerWindow)
{
window.Owner = ownerWindow;
}
}
}
Here I added a View, which I initializes for several displays.
<Window x:Class="Clock_ScreenSaver.Views.ClockWindow"
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:local="clr-namespace:Clock_ScreenSaver.Views"
mc:Ignorable="d"
Title="ClockWindow"
Height="{Binding DisplayHeight}"
Width="{Binding DisplayWidth}"
AllowsTransparency="True"
Background="Black"
Cursor="None"
ShowInTaskbar="False"
KeyDown="ClockWindow_KeyDown"
MouseMove="ClockWindow_MouseMove"
MouseDown="ClockWindow_MouseDown"
Closing="ClockWindowClosing"
Loaded="ClockWindowLoaded"
WindowStyle="None"
ResizeMode="NoResize">
<Grid Name="WindowGrid">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="300"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="300"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Grid.Row="1" Grid.Column="1" CornerRadius="360" BorderBrush="#FFDF66" BorderThickness="5" Background="#2D2D30">
<StackPanel>
<Label Foreground="#FFDF66" Margin="0,15,0,0" FontSize="25" FontFamily="Arial" HorizontalAlignment="Center">DIGICLOCK</Label>
<StackPanel Background="#3F3F46" Margin="0,20,0,5" Width="280" Height="100">
<Label Content="{Binding ClockTime}" Name="timelbl" Margin="0,20,0,0" Foreground="#FFDF66" FontSize="40" FontFamily="Arial" HorizontalAlignment="Center"></Label>
</StackPanel>
<StackPanel Background="#3F3F46" Margin="0,0,0,10" Width="280" Height="50">
<Label Content="{Binding ClockDate}" Name="datelbl" Margin="0,8,0,0" Foreground="#FFDF66" FontSize="20" FontFamily="Arial" HorizontalAlignment="Center"></Label>
</StackPanel>
<Button Width="60" Padding="5,5,5,5" Background="#FFDF66" FontSize="10" FontFamily="Arial" Foreground="#333333" BorderThickness="0" Name="QuitBtn" Click="QuitBtn_Click">
Quit
</Button>
</StackPanel>
</Border>
</Grid>
</Window>

WPF Need to find a way to identify TypeOf on custom Page class

I have a Window class called MainWindow, and in its constructor, builds a default Page class I call, MonitorPage that populates my window with this page at launch. In my MainWindow, I have three buttons that act as page tabs or menu buttons that upon clicking them will create an instance of a different Page class, in my case I have three unique pages. MonitorPage, DataBasePage, HelpPage. In my MainWindow, I want to "grey-out" the tab button when that corresponding page is up. I have a method in MainWindow called, PageState(), that tries to identify which page is currently up to enable or disable and grey out the tabs. My problem is that I get a NullReferenceException in my method at the first IF check.
The Error I'm Getting:
System.NullReferenceException: 'Object reference not set to an instance of an object.'
System.Windows.Controls.ContentControl.Content.get returned null.
C#:
using System.Collections.ObjectModel;
using System.IO;
using System.Windows;
using System.Windows.Media;
namespace EyeInTheSky
{
/// <summary>
/// Interaction logic for MainWindow.xaml + backend code for FileSystemWatcher project
/// </summary>
public partial class MainWindow : Window
{
#region Fields
private FileSystemWatcher _watcher = new FileSystemWatcher();
private ObservableCollection<string[]> _eventList = new ObservableCollection<string[]>();
#endregion
public MainWindow()
{
InitializeComponent();
Main.Content = new MonitorPage(ref _watcher, ref _eventList);
PageState();
}
private void PageState()
{
if (Main.Content.GetType() == typeof(MonitorPage))
{
Menu_MonitorButton.IsEnabled = false;
Menu_MonitorButton.Background = new SolidColorBrush(Color.FromRgb(88, 88, 95));
Menu_DataBaseButton.IsEnabled = true;
Menu_HelpButton.IsEnabled = true;
}
else if (Main.GetType() == typeof(DataBasePage))
{
Menu_MonitorButton.IsEnabled = true;
Menu_DataBaseButton.IsEnabled = false;
Menu_DataBaseButton.Background = new SolidColorBrush(Color.FromRgb(88, 88, 95));
Menu_HelpButton.IsEnabled = true;
}
else
{
Menu_MonitorButton.IsEnabled = true;
Menu_DataBaseButton.IsEnabled = true;
Menu_HelpButton.IsEnabled = false;
Menu_HelpButton.Background = new SolidColorBrush(Color.FromRgb(88, 88, 95));
}
}
private void Menu_MonitorButton_Click(object sender, RoutedEventArgs e)
{
PageState();
Main.Content = new MonitorPage(ref _watcher, ref _eventList);
}
private void MenuStrip_DataBaseButton_Click(object sender, RoutedEventArgs e)
{
PageState();
Main.Content = new DataBasePage(ref _eventList);
}
private void MenuStrip_HelpButton_Click(object sender, RoutedEventArgs e)
{
PageState();
Main.Content = new HelpPage();
}
}
}
XAML:
<Window x:Name="Home" x:Class="EyeInTheSky.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:local="clr-namespace:EyeInTheSky"
xmlns:System="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="Eye In The Sky - Windows File System Watcher" Height="450" Width="1105" WindowStartupLocation="CenterScreen" ResizeMode="NoResize" TextOptions.TextFormattingMode="Ideal" Background="#FF39393E" Foreground="#FFE4E4E4" FontFamily="Roboto">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="27*"/>
<RowDefinition Height="394*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="240*"/>
<ColumnDefinition Width="859*"/>
</Grid.ColumnDefinitions>
<Frame x:Name="Main" Height="421" VerticalAlignment="Top" Grid.RowSpan="2" Grid.ColumnSpan="2" Panel.ZIndex="1"/>
<DockPanel HorizontalAlignment="Left" Height="27" LastChildFill="False" VerticalAlignment="Top" Width="240" Panel.ZIndex="10000">
<StackPanel x:Name="Menu" Orientation="Horizontal" HorizontalAlignment="Left" Height="27" VerticalAlignment="Top" Width="240" Background="#FF4E4E53">
<Button x:Name="Menu_MonitorButton" Content="Monitor" Width="80" Click="Menu_MonitorButton_Click" Background="#FF4E4E53" BorderBrush="#FF585858" Foreground="LightGray" BorderThickness="1,0"/>
<Button x:Name="Menu_DataBaseButton" Content="Data Base" Width="80" Click="MenuStrip_DataBaseButton_Click" Background="#FF4E4E53" BorderBrush="#FF585858" Foreground="LightGray" BorderThickness="1,0"/>
<Button x:Name="Menu_HelpButton" Content="About" Width="80" Click="MenuStrip_HelpButton_Click" Background="#FF4E4E53" BorderBrush="#FF585858" Foreground="LightGray" Padding="0,1,1,1" BorderThickness="1,0,2,0"/>
</StackPanel>
</DockPanel>
</Grid>
</Window>

Window.ShowDialog failes on return

I have a custom input dialog box that request an user's name and a reson (because reasons) for doing a certain action in my application. The user clicks on a button on the main window and the dialog box shows, as it should.
The user then enters his/her name and the reason and clicks ok. The dialog then closes but I ( the program) never receives an answer. Here is my XAML for the input dialog:
<Window x:Class="Sequence_Application_2.GUI.ForcedRackInput"
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"
mc:Ignorable="d"
Title="Forcera Rack" Height="300" Width="300"
WindowStartupLocation="CenterScreen">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="21*"/>
<ColumnDefinition Width="274*"/>
</Grid.ColumnDefinitions>
<TextBox Name="OperatorNameText" HorizontalAlignment="Left" Height="23" Margin="15,36,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Grid.ColumnSpan="2"/>
<Label x:Name="label" Content="Namn:" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Grid.ColumnSpan="2"/>
<Label x:Name="label1" Content="Orsak:" HorizontalAlignment="Left" Margin="10,72,0,0" VerticalAlignment="Top" Grid.ColumnSpan="2"/>
<Border BorderThickness="1" BorderBrush="Black" Grid.ColumnSpan="2" Margin="0,0,0,0.5">
<TextBox Name="ReasonText" Margin="15,98,15,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="116" />
</Border>
<Button Name="OkButton" IsDefault="True" Content="OK" Click="OkButtonPressed" HorizontalAlignment="Left" Margin="26.202,233,0,0" VerticalAlignment="Top" Width="75" Cursor="Arrow" Grid.Column="1"/>
<Button Name="CancelButton" IsCancel="True" Content="Avbryt" Margin="152.202,233,47,0" VerticalAlignment="Top" Cursor="Arrow" Grid.Column="1"/>
</Grid>
</Window>
And here is the "behind code":
namespace Sequence_Application_2.GUI
{
using System.Windows;
public partial class ForcedRackInput : Window
{
public string OperatorName { get { return OperatorNameText.Text; } }
public string ForcedRackReason { get { return ReasonText.Text; } }
public ForcedRackInput()
{
InitializeComponent();
}
private void OkButtonPressed(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
}
}
}
and this is how I call the code (from a model, not a "window class")
public void ForceClosingRack(Flow forcedFlow)
{
var forcedRackWindow = new ForcedRackInput();
string operatorName = "";
string reasonForForced = "";
if( forcedRackWindow.ShowDialog() == true)
{
operatorName = forcedRackWindow.OperatorName;
reasonForForced = forcedRackWindow.ForcedRackReason;
}
} // code jumps from "if(forcedRackWindow.... to this line when ok is clicked in the dialog
Looked for the solution for some time now and I just about to change career
Thanks for your time
My guess is that the problem doesn't lie in the code, which seems to be fine, but in your if statement.
When you run your program in Debug mode it should work as expected.
My guess is that you are assigning the variables operatorName and reasonForForced inside your if statment but they are not used anywhere else in the program and hence the whole if statement is ignored by the compiler and not present when running in Release mode.
A small modification in your code which embeds different behaviour depending on the variable values can prove my guess:
private void Button_Click(object sender, RoutedEventArgs e)
{
var forcedRackWindow = new ForcedWindow();
string operatorName = "foo";
string reasonForForced = "foo";
if (forcedRackWindow.ShowDialog() == true)
{
operatorName = forcedRackWindow.OperatorName;
reasonForForced = forcedRackWindow.ForcedRackReason;
}
if(!operatorName.Equals(reasonForForced))
{
MessageBox.Show("We are not the same");
}
}

C# User Must Add Multiple Buttons to WPF and Buttons Must Persist

I am attempting to create a program in which the User can create multiple profiles. These profiles can be accessed via buttons that appear as each profile is completed.
My problem:
I have no clue how to make the created buttons persist after the program is exited(I need to save the buttons?)
Visually, this is program's process: 1) Enter your information, click continue 2) View a display page of what you entered, click done. 3) This adds a button to the final window, the button of course takes you to 4) Your profile you just created.
After this, the program ends and nothing is saved. I'm fairly new to c# and am quite confused on how to "save" multiple buttons without massively complicating the code. I'm a complete noob to c# and have a little Java experience. Am I going about this correctly? I'm pretty sure its possible but have no idea to go about it.
I will include my code below. I'm working in visual studios 2012. any help would be appreciated!
MainWindow XAML:
<Window x:Class="VendorMain.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Label Content="FirstName" HorizontalAlignment="Left" Margin="63,45,0,0" VerticalAlignment="Top"/>
<Label Content="LastName" HorizontalAlignment="Left" Margin="63,71,0,0" VerticalAlignment="Top"/>
<Label Content="Image" HorizontalAlignment="Left" Margin="63,102,0,0" VerticalAlignment="Top"/>
<Image Name="imgPhoto" Stretch="Fill" Margin="63,133,303,69"></Image>
<Button Name="UploadImageButton" Content="Upload Image" HorizontalAlignment="Left" Margin="130,105,0,0" VerticalAlignment="Top" Width="84" Click="UploadImageButton_Click"/>
<TextBox Name="AssignFirstName" Text="{Binding SettingFirstname}" HorizontalAlignment="Left" Height="23" Margin="130,48,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" />
<TextBox Name="AssignLastName" Text="{Binding SettingLastName}" HorizontalAlignment="Left" Height="23" Margin="130,75,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
<Button Name="ContinueToDisplayWindow" Content="Continue" HorizontalAlignment="Left" Margin="409,288,0,0" VerticalAlignment="Top" Width="75" Click="ContinueToDisplayWindow_Click" />
</Grid>
MainWindow Code:
namespace VendorMain
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void UploadImageButton_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog op = new OpenFileDialog();
op.Title = "Select a picture";
op.Filter = "All supported graphics|*.jpg;*.jpeg;*.png|" +
"JPEG (*.jpg;*.jpeg)|*.jpg;*.jpeg|" +
"Portable Network Graphic (*.png)|*.png";
if (op.ShowDialog() == true)
{
imgPhoto.Source = new BitmapImage(new System.Uri(op.FileName));
//SettingImage.Source = imgPhoto.Source;
}
}
private void ContinueToDisplayWindow_Click(object sender, RoutedEventArgs e)
{
DisplayPage displaypg = new DisplayPage();
displaypg.DpFirstName.Content = AssignFirstName.Text;
displaypg.DpLastName.Content = AssignLastName.Text;
displaypg.DpImage.Source = imgPhoto.Source;
displaypg.Show();
}
}
}
DisplayPage XAML:
<Window x:Class="VendorMain.DisplayPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DisplayPage" Height="300" Width="525">
<Grid>
<Label Name="DpFirstName" Content="{Binding getFirstNamePermenent}" HorizontalAlignment="Left" Margin="86,55,0,0" VerticalAlignment="Top"/>
<Label Name="DpLastName" Content="{Binding getLastNamePermenent}" HorizontalAlignment="Left" Margin="87,80,0,0" VerticalAlignment="Top"/>
<Image Name="DpImage" HorizontalAlignment="Left" Height="100" Margin="94,111,0,0" VerticalAlignment="Top" Width="100"/>
<Button Name="ButtonizeThisProfile_Button" Content="Done" HorizontalAlignment="Left" Margin="420,238,0,0" VerticalAlignment="Top" Width="75" Click="ButtonizeThisProfile_Button_Click"/>
</Grid>
DisplayPage Code:
namespace VendorMain
{
/// <summary>
/// Interaction logic for DisplayPage.xaml
/// </summary>
public partial class DisplayPage : Window
{
public Button bot1;
public DisplayPage()
{
InitializeComponent();
}
private void newBtn_Click(object sender, RoutedEventArgs e)
{
carryToFinalView();
}
private void ButtonizeThisProfile_Button_Click(object sender, RoutedEventArgs e)
{
UserProfiles uPro = new UserProfiles();
System.Windows.Controls.Button newBtn = new Button();
newBtn.Content = "Person1";
newBtn.Name = "NewProfileButtonAccess";
newBtn.Click += new RoutedEventHandler(newBtn_Click);
uPro.ButtonArea.Children.Add(newBtn);
uPro.Show();
}
public void carryToFinalView()
{
DisplayPage displaypg = new DisplayPage();
displaypg.DpFirstName.Content = DpFirstName.Content;
displaypg.DpLastName.Content = DpLastName.Content;
displaypg.DpImage.Source = DpImage.Source;
displaypg.Show();
}
}
}
UserProfile XAML:
<Window x:Class="VendorMain.UserProfiles"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="UserProfiles" Height="300" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".8*" />
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="6*"/>
<RowDefinition Height="11*"/>
</Grid.RowDefinitions>
<Label Content="User Profiles: " HorizontalAlignment="Left" Margin="37,47,0,0" VerticalAlignment="Top"/>
<StackPanel Name="ButtonArea" Grid.Column="2" Grid.Row="2">
</StackPanel>
<Button Name="AddAnotherProfileButton" Content="Button" HorizontalAlignment="Left" Margin="35,146,0,0" Grid.Row="1" VerticalAlignment="Top" Width="75" Click="AddAnotherProfileButton_Click"/>
</Grid>
UserProfile Code:
namespace VendorMain
{
public partial class UserProfiles : Window
{
public UserProfiles()
{
InitializeComponent();
}
private void AddAnotherProfileButton_Click(object sender, RoutedEventArgs e)
{
MainWindow mw = new MainWindow();
mw.Show();
}
}
}
As a self proclaimed 'noob', I fear that you won't receive an answer here. I certainly don't have time to repeatedly come back to answer a whole continuing stream of related questions. I also don't have time to provide you with a complete solution. However, I am happy to provide you with sort of 'pseudo code' to at least point you in the right direction... you will have to do a lot of this yourself.
So first things first, as mentioned in a comment, although it is possible, we don't generally save the UI Button objects, but instead we save the data that relates to the user profiles. Therefore, if you haven't done this already, create a User class that has all of the relevant properties. Implement the INotifyPropertyChanged Interface in it and add the SerializableAttribute to the class definition... this will enable you to save this class type as binary data.
Next, in your UI, don't add each Button in xaml... there's a better way. One way or another, add a collection property of type User or whatever your class is called, and set this as the ItemsSource of a ListBox. The idea here is to add a DataTemplate for your User type which will display each of the User items in the collection as a Button:
<DataTemplate x:Key="UserButtonTemplate" DataType="{x:Type DataTypes:User}">
<Button Text="{Binding Name}" Width="75" Click="AddAnotherProfileButton_Click" />
</DataTemplate>
You can find out more about DataTemplates in the Data Templates article.
Implementing this collection allows you to have and display any number of user profiles in your UI, rather than being restricted by screen size as your original example would be.
Now finally, on to saving the data... this can be achieved relatively simply using the following code:
try
{
using (Stream stream = File.Open("ProfileData.bin", FileMode.Create))
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter .Serialize(stream, usersList);
}
}
catch { }
One thing to note is that WPF wants us to use the ObservableCollection<T> class when displaying data in the UI, but this class causes problems when serializing data with this method... therefore, you will need to convert your ObservableCollection<T> to a List<T> or similar. However, this can be easily achieved:
List<User> usersList = users.ToList();
You can find out how to de-serialize your data from the C# Serialize List tutorial. You would deserialize (or load the data from the saved file) each time your application starts and re-save the file each time the program closes. You can add an event handler to the Application.Deactivated Event or the Window.Closing which gets called when the application closes, so you can put your code to save the file in there.
Well, I took longer and wrote more than I had expected, so I hope that helps.

Categories

Resources