How can i change a Page in my wpf Main Window? - c#

i want to switch pages that are hosted on my main window. The first page (at App Start) is beeing shown correctly. But if i want to change the page it won´t happen. I even don´t get an error. It just shows the first page! Here´s my code:
The constructor of MainWindow:
public MainWindow(SchraubUser _schraubUser, string page = "")
{
schraubUser = _schraubUser;
db = new AccessDatabase(schraubUser._DATABASE_PATH);
ViewModel.ViewModel wzViewModel = new ViewModel.ViewModel(schraubUser, db);
InitializeComponent();
if (page == "")
{
Main.Content = new View.Werkzeug_Window(wzViewModel);
}
else
{
Main.Content = new View.Freigaben(wzViewModel);
}
}
At Application start the optional variable is "" so the mainwindow will display View.Werkzeug_Window (works correctly).
Here`s the code for changing the page:
private void Button_Freigaben_Click(object sender, RoutedEventArgs e)
{
mainWindow = new MainWindow(sb_vm.schraubUser, "Freigabe");
}
But it will still show the first page. Why is that?
XAML of MainWindow:
<Window x:Class="SchrauberDB.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:SchrauberDB"
mc:Ignorable="d"
Title="MainWindow" Height="750" Width="1100"
WindowState="Maximized">
<Grid x:Name="mainGrid">
<Frame x:Name="Main" />
</Grid>
</Window>

This is so embarrassing...
private void Button_Freigaben_Click(object sender, RoutedEventArgs e)
{
mainWindow = new MainWindow(sb_vm.schraubUser, "Freigabe");
mainWindow.Show();
}

Related

WPF - Changing Focus from a RichTextBox causes a InvalidOperationException

Running into a strange issue when I have to switch focus from a RichTextBox. The xaml for my application is as follows:
<Window Name="MyWindow" x:Class="WpfBasics.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:WpfBasics"
mc:Ignorable="d"
Title="MainWindow" Height="600" Width="400">
<StackPanel>
<TextBlock>Box 1:</TextBlock>
<RichTextBox x:Name="Box1" TextChanged="Box1_TextChanged" />
<TextBlock>Box 2:</TextBlock>
<RichTextBox x:Name="Box2" />
</StackPanel>
</Window>
With the following codebehind (only the relevant bit):
private void Box1_TextChanged(object sender, TextChangedEventArgs e)
{
Box2.Focus();
}
The moment I use Box1, Focus throws the following exception:
System.InvalidOperationException: 'Cannot Reopen undo unit while another unit is already open.'
Looking into the CallStack I believe the issue is caused by the LostFocus event handler on a RichTextBox.
Based on the information you gave, I created a sample project that seems to work. Give this a shot:
private void Box1_TextChanged(object sender, TextChangedEventArgs e)
{
RichTextBox textBox = sender as RichTextBox;
var text = new TextRange(textBox.Document.ContentStart, textbox.Document.ContentEnd).Text;
if (IsValid(text))
{
Dispatcher.BeginInvoke((Action)ChangeFocus);
}
}
private void ChangeFocus()
{
Box2.Focus();
}
private bool IsValid(string text)
{
var plainText = text.Substring(0, text.Length - 2);
if (plainText == "hello world")
return true;
return false;
}

How to show programmatically FocusVisualStyle?

Afters attemps I could tell that the FocusVisualStyle is only activated by the keyboard (tab and arrows keys).
Try to make the FocusVisualStyle to be applied after the component is loaded, it is impossible to do, There is an easy way to get around this problem?
I found this:
- focus visual not showing when navigating focus programically
- How do WPF buttons decide to show FocusVisualStyle?
- http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/99856840-f8ef-4547-9150-c4c46ec2f3df
But none shows a definite solution (without overwriting the component), and I could not write, can someone help?
I am not pretty sure I understand your issue, but I tried the example in one of the links and I was able to move focus to next component from code behind exactly as you would do using keyboard. Here is the code.
<Window x:Class="WpfApplication1.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"
xmlns:local="clr-namespace:WpfApplication1" Loaded="OnLoaded"
>
<StackPanel Margin="10">
<TextBox Margin="10" x:Name="a" >A</TextBox>
<TextBox Margin="10" x:Name="b" >B</TextBox>
<Button Focusable="False" Click="OnClick">Move Focus</Button>
</StackPanel>
</Window>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void OnLoaded(object sender, RoutedEventArgs e) {
a.Focus();
}
private void OnClick(object sender, RoutedEventArgs e) {
var request = new TraversalRequest(FocusNavigationDirection.Next);
var elementWithFocus = FocusManager.GetFocusedElement(FocusTest) as UIElement;
if (elementWithFocus != null)
elementWithFocus.MoveFocus(request);
}
}

Why isn't change button content working

I have this code:
private void ModifyButton_Click(object sender, RoutedEventArgs e)
{
ModifyButton.Content = "Another button name";
}
But it doesn't work. I mean, the modify button content doesn't change but the program doesn't fail or throw any exception.
I'm trying to modify the button name in order to change it's behavior (kinda Edit/Save) within the same button. Is this not possible using C#/WPF?
Thanks in advance.
EDIT:
XAML:
<Button Name="ModifyButton" Content="Modificar" Margin="5,10,0,0" Height="23" Width="120" HorizontalAlignment="Left" Click="ModifyButton_Click"></Button>
WEIRD BEHAVIOR: If I put a MessageBox.Show call after the change of the button content, then, while the message box is displayed the button dislay the new (changed) name, but after the message box is closed, then it shows it's original text.
I guess that the XAML of your UI is not bound to the value of your button. Did you check the DataBinding?
[EDIT]
Your magic information here is that you use ShowDialog(). As you already guessed, this influences your UI thread and therefore the display behavior. ShowDialog() displays the Form as a modal dialog and blocks your UI thread and therefore blocks the refresh of it. This may cause all sorts of weird behavior.
This is what i have and it works:
Window 1
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<Button Name="ModifyButton" Content="Open Dialog" Margin="80,104,78,0" Height="23" Click="ModifyButton_Click" VerticalAlignment="Top"></Button>
</Grid>
</Window>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void ModifyButton_Click(object sender, RoutedEventArgs e)
{
Window2 win2 = new Window2();
win2.ShowDialog();
}
}
Window 2
<Window x:Class="WpfApplication1.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window2" Height="300" Width="300">
<Grid>
<Button Name="ModifyButton" Content="Modificar" Margin="80,104,78,0" Height="23" Click="ModifyButton_Click" VerticalAlignment="Top"></Button>
</Grid>
</Window>
public partial class Window2 : Window
{
public Window2()
{
InitializeComponent();
}
private void ModifyButton_Click(object sender, RoutedEventArgs e)
{
ModifyButton.Content = "Another button name";
}
}

Setting control to be content of several controls

I have a control which i'm putting in dialog as a content. Due to relization of this dialog i have to create it every time when i need it(Show/Hide won't do the trick). I want my control to remember field content beetween calls. While i can apply viewmodel to achieve this i prefer just keep control as a field and assing it as content of dialog every time i need it. But i run into following error:
"Specified element is already the logical child of another element. Disconnect it first."
I tried to assing null to dialog window's content before closing it, but it doesn't solve the problem. Is there anything i can do?
Setting window.Content = null works fine for me. Following is the code I used:
public partial class MainWindow : Window
{
TextBlock textBlock = new TextBlock();
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
TestWindow testWindow = new TestWindow();
testWindow.Content = textBlock;
testWindow.Closing += HandleTestWindowClosing;
testWindow.Show();
}
void HandleTestWindowClosing(object sender, System.ComponentModel.CancelEventArgs e)
{
var testWindow = sender as TestWindow;
if(testWindow!=null)
{
testWindow.Content = null;
testWindow.Closing -= HandleTestWindowClosing;
}
}
}
Check out the following working example. It isn't exactly your scenario, but pretty close. The key is setting the 'Child' property to null. It moves the TextBox from the top border to the bottom.
<Window x:Class="SO.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>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Button Grid.Row="0" Click="Move_Click">Move</Button>
<Border x:Name="topBorder" Grid.Row="1">
<TextBlock x:Name="ctrl">Some Text Block</TextBlock>
</Border>
<Border x:Name="bottomBorder" Grid.Row="2"/>
</Grid>
</Window>
and the code behind:
using System.Windows;
namespace SO
{
public partial class MainWindow :Window
{
public MainWindow( )
{
InitializeComponent( );
}
private void Move_Click( object sender, RoutedEventArgs e )
{
this.topBorder.Child = null;
this.bottomBorder.Child = this.ctrl;
}
}
}

WPF MenuItem vs Button behavior in new window when mouse still down

I didn't know how to make the 'issue' (different behavior) more clear in the title, but I'll explain here.
In our WPF application, we're using the DataGrid control to list a number of entities. After double clicking a row, we open a new Window and in that Window, there are among other things a couple of MenuItem controls.
The problem is that when the Window opens on a position where one of the menu items is right under the mouse pointer, the menu item is actually clicked there at the mouse up of the double click.
When we use a button instead, the button click event is not fired automatically in the same situation.
We are now thinking about using buttons instead of menu items (or creating custom menus), but perhaps someone here has an explanation or solution to alter this behavior? Personally, I can't think of a case where this would be beneficial at all. Thanks in advance!
Example code is below. To see what I mean, double click the DataGrid row to open the new window and hold down the mouse button, move to the menu item and let the mouse button go (in TestWindow.xaml, exchange the MenuItem for a Button control to see the difference in behavior):
MainWindow.xaml
<Window x:Class="WpfApplication2.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">
<Window.Resources>
<Style x:Key="DataGridRowStyle"
TargetType="{x:Type DataGridRow}">
<EventSetter Event="MouseDoubleClick" Handler="DataGridRow_MouseDoubleClick" />
</Style>
</Window.Resources>
<DataGrid RowStyle="{StaticResource DataGridRowStyle}" x:Name="MyDataGrid">
<DataGrid.Columns>
<DataGridTextColumn Header="String" Binding="{Binding}" IsReadOnly="True" />
</DataGrid.Columns>
</DataGrid>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
ObservableCollection<string> myCollection = new ObservableCollection<string>();
myCollection.Add("test");
MyDataGrid.ItemsSource = myCollection;
this.DataContext = this;
}
private void DataGridRow_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
TestWindow window = new TestWindow();
window.Show();
window.Activate();
}
}
TestWindow.xaml
<Window x:Class="WpfApplication2.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TestWindow" Height="300" Width="300">
<Grid>
<MenuItem Header="Test" Click="Button_Click" />
</Grid>
TestWindow.xaml.cs
public partial class TestWindow : Window
{
public TestWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
You could try modifying your DataGridRow_MouseDoubleClick handler as follows:
private void DataGridRow_MouseDoubleClick( object sender, MouseButtonEventArgs e )
{
this.Dispatcher.BeginInvoke(
( Action )delegate
{
TestWindow window = new TestWindow();
window.Show();
window.Activate();
},
System.Windows.Threading.DispatcherPriority.Background,
null
);
}
That might solve the problem by letting the outstanding events "settle" before creating the new window.

Categories