How to prevent TabControl from switching tabs when Button is pressed? - c#

I've got a new WPF (.NET Framework 4.7.2) application with a Window XAML defined as below:
<Window x:Class="WpfApp5.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="200" Width="300">
<Grid>
<TabControl>
<TabItem Header="Tab">
<ToolBarTray>
<ToolBar>
<Button>Button</Button>
</ToolBar>
</ToolBarTray>
</TabItem>
<TabItem Header="Tab">
<ToolBarTray>
<ToolBar>
<Button>Button</Button>
</ToolBar>
</ToolBarTray>
</TabItem>
</TabControl>
</Grid>
</Window>
and the code behind:
using System.Windows;
namespace WpfApp5
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
}
}
Now follow the steps below:
Run the app and switch to the second Tab
Switch back to the first Tab and press Button
This makes the TabControl switch to the second Tab for no apparent reason as seen here:
Can someone elighten me why this happens and how to fix it so it does not switch the tab on a Button press, please?
Many thanks!
Related Links:
https://github.com/dotnet/wpf/issues/2278

A good enough soluton for me was to set x:Name on the TabControl and set FocusManager.FocusedElement to the TabControl name:
<Window x:Class="WpfApp5.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="200" Width="300"
FocusManager.FocusedElement="{Binding ElementName=tabControl}">
<Grid>
<TabControl x:Name="tabControl">
<TabItem Header="Tab">
<ToolBarTray>
<ToolBar>
<Button>Button</Button>
</ToolBar>
</ToolBarTray>
</TabItem>
<TabItem Header="Tab">
<ToolBarTray>
<ToolBar>
<Button>Button</Button>
</ToolBar>
</ToolBarTray>
</TabItem>
</TabControl>
</Grid>
</Window>
Still got no idea why this happens though so it's not a perfect answer.

Related

WindowChrome/title bar theme not syncing with loaded PresentationFramework/XAML

I'm attempting to build a WPF app which uses the Royale theme from XP Media Center. I've correctly referenced the PresentationFramework.Royale DLL and the corresponding XAML resources into my App.xaml, and can confirm that the controls are very much Royale-themed:
However, the window itself fails to be, and the WindowChrome/title bar/window border theme fails to sync up, remaining the standard presentation style for Windows 10. This, of course, is what I'm trying to replicate, at least visually:
Relevant XAML, if useful (all *.cs files are default):
App.xaml:
<Application x:Class="ExampleRoyale.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Ariadne"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/PresentationFramework.Royale;component/themes/Royale.NormalColor.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
MainWindow.xaml:
<Window x:Class="ExampleRoyale.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:ExampleRoyale"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Button Content="Button" HorizontalAlignment="Left" Margin="94,39,0,0" VerticalAlignment="Top" Width="120"/>
<ComboBox HorizontalAlignment="Left" Margin="94,12,0,0" VerticalAlignment="Top" Width="120"/>
<Label Content="Label" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="79"/>
<Label Content="Label 2" HorizontalAlignment="Left" Margin="10,39,0,0" VerticalAlignment="Top" Width="79"/>
<RadioButton Content="RadioButton" HorizontalAlignment="Left" Margin="228,15,0,0" VerticalAlignment="Top" Width="102"/>
<RadioButton Content="RadioButton 2" HorizontalAlignment="Left" Margin="228,44,0,0" VerticalAlignment="Top" Width="102"/>
<TabControl Margin="82,72,82,71">
<TabItem Header="TabItem">
<Grid Background="#FFE5E5E5"/>
</TabItem>
<TabItem Header="TabItem">
<Grid Background="#FFE5E5E5"/>
</TabItem>
</TabControl>
</Grid>
</Window>
Is there a manner to apply the Royale theme to the window container itself, or is Royale controls the closest I will get?
Is there a manner to apply the Royale theme to the window container itself
Unfortunately (?) the window container itself is not part of WPF so there is no custom style for it. It's part of the operating system.
You may be able to make Windows 10 look like Vista by changing the OS settings as a user (I haven't tried) but this is not related to WPF.

How can I reuse same "Content Controller" in different tab (child) in XAML?

I have a TabControl in a XAML file like this:
<UserControl d:DesignHeight="300" d:DesignWidth="400">
<TabControl Style="{DynamicResource WizardTabControlStyle}">
<TabItem >
<local:Tab1/>
</TabItem>
<TabItem >
<local:Tab2/>
</TabItem>
<TabItem >
<local:Tab3/>
</TabItem>
</TabControl>
and every tab is defined in another xaml file:
<UserControl d:DesignHeight="450" d:DesignWidth="794">
<DockPanel DataContext="{Binding Model1}">
<GroupBox Header="{concept:Intl Key=Geometry, DefaultText='G1'}" DockPanel.Dock="Top" MinHeight="165">
<Grid>
// Common view
</Grid>
</GroupBox>
<GroupBox DockPanel.Dock="Bottom" Header="{concept:Intl Key=G2, DefaultText='G2'}" DataContext="{Binding G2}" Padding="0,10">
<Grid>
// other stuff
</Grid>
</GroupBox>
</DockPanel>
Other tab views are the same as this.
What I want to do is that define a graphical view (OpenGL) in the TabControl and then in the single tab XAML, I want a reference to that view. Every tab sin the "//Common view" should have the same OpenGL view defined in the Tab Control.
Is that possible?

Best way to go about switching views using MVVM

I'm working on a game where I am using a UI framework which works with XAML and MVVM. I have managed to get my framework hooked up and I am able to switch between views. Right now I am using data-templates along with the ContentControl to switch views, I am also using a state-like pattern to switch and I was wondering if this is a good approach to use? I am having a small problem with my views, the way I have things set up currenly I have my MainWindow.xaml which contains a data-template to my other xaml files. The problem is the views just get added to the MainWindow.xaml and I'm wondering if there is a way to hide the previous view/content so it looks as if I'm switching between windows/views rather than just adding to them. Here is a screenshot to illustrate what I currently have.Image of project. My xaml files are very simple and just contain a button for now, here are my xaml files:
`
MainWindow.xaml
<Grid
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"
xmlns:local="clr-namespace:PsalmsOfEia"
xmlns:viewmodels="clr-namespace:PsalmsOfEia.UI.Menus.ViewModels"
xmlns:views="clr-namespace:PsalmsOfEia.UI.Menus.Views">
<Grid.DataContext>
<viewmodels:MainViewModel />
</Grid.DataContext>
<Grid.Resources>
<DataTemplate DataType="{x:Type viewmodels:LoginViewModel}">
<views:LoginView/>
</DataTemplate>
</Grid.Resources>
<DockPanel LastChildFill="True">
<StackPanel>
<ContentControl Content="{Binding SelectedViewModel}"/>
<Button Content="Login" Command="{Binding ChangeCommand}"/>
</DockPanel>
</Grid>
LoginView.xaml
<UserControl x:Class="PsalmsOfEia.UI.Menus.Views.LoginView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:PsalmsOfEia"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
xmlns:viewmodels="clr-namespace:PsalmsOfEia.UI.Menus.ViewModels"
xmlns:views="clr-namespace:PsalmsOfEia.UI.Menus.Views">
<UserControl.DataContext>
<viewmodels:LoginViewModel />
</UserControl.DataContext>
<UserControl.Resources>
<DataTemplate DataType="{x:Type viewmodels:CreateCharacterViewModel}">
<views:CreateCharacterView/>
</DataTemplate>
</UserControl.Resources>
<StackPanel>
<ContentControl Content="{Binding SelectedViewModel}"/>
<Button Content="Click Here" Command="{Binding LoginCommand}"/>
</StackPanel>
</UserControl>
`
Could anyone tell me if there is a better way of switching views as well as how to hide the content of the previous views (since at the moment everything is being added to the main window).
Thanks
-Joshmond
Not really sure what you're looking for but I use a TabControl
<TabControl>
<TabItem Header="Tab1">
<local:UserControl1/>
</TabItem>
<TabItem Header="Tab2">
<local:UserControl2/>
</TabItem>
<TabItem Header="Tab3">
<local:UserControl3/>
</TabItem>
</TabControl>
I try to minimise the amount of XAML in one file, so I create a UserControl and add them into the main view.
Im using stackpanel and usercontrol.
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel x:Name="myStackpanel1" Grid.Row="0" />
<StackPanel x:Name="myStackpanel2" Grid.Row="1" />
<Button x:Name="myButton" Width="200" Height="30" Grid.Row="2" Click="myButton_Click" Content="Click Me SP1" />
<Button x:Name="myButton2" Width="200" Height="30" Grid.Row="3" Click="myButton2_Click" Content="Click Me2 SP2" />
</Grid>
Code
private int i,j = 0;
public MainWindow()
{
InitializeComponent();
}
private void myButton_Click(object sender, RoutedEventArgs e)
{
i++;
if (i % 2 == 0)
{
myStackpanel1.Children.Clear();
myStackpanel1.Children.Add(new UserControl1());
}
else
{
myStackpanel1.Children.Clear();
myStackpanel1.Children.Add(new UserControl2());
}
}
private void myButton2_Click(object sender, RoutedEventArgs e)
{
j++;
if (j % 2 == 0)
{
myStackpanel2.Children.Clear();
myStackpanel2.Children.Add(new UserControl2());
}
else
{
myStackpanel2.Children.Clear();
myStackpanel2.Children.Add(new UserControl1());
}
}

How to avoid repeated xaml code

I have a small UI in XAML where I need to display twice the same thing in the same window. I created a Resources with the code, but can't figure out how to display it.
the resources :
<max:MaxUserControl.Resources>
<DataTemplate x:Key="tInfo">
<max:MaxGrid>
<max:MaxGrid.ColumnDefinitions>
...
</max:MaxGrid.ColumnDefinitions>
<max:MaxGrid.RowDefinitions>
...
</max:MaxGrid.RowDefinitions>
...
</max:MaxGrid>
</DataTemplate>
</max:MaxUserControl.Resources>
The only difference between both UI is the Datacontext, so I wanted to do something like :
<max:MaxStackPanel Grid.Row="1" Grid.Column="0" Template="{StaticResource ResourceKey=tInfo}" DataContext="{Binding ElementName=dtgEmployeeOccupation, Path=SelectedItem, Mode=OneWay}"/>
<max:MaxStackPanel Grid.Row="0" Grid.Column="1" Template="{StaticResource ResourceKey=tInfo}" DataContext="{Binding Path=ANOTHERBINDING"/>
What control I should use to achieve this?
Create UserControl and reuse where you want. At first you should create
UserControl, then add some necessary controls inside your UserControl. For example, we are creating UserControl and it would be called FooUserControl:
<UserControl x:Class="OpenExcelFileAndConvertToArray.FooUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:OpenExcelFileAndConvertToArray"
mc:Ignorable="d">
<Grid>
<StackPanel Orientation="Horizontal">
<TextBlock Text="SomeText"/>
<Button Content="Delete"/>
</StackPanel>
</Grid>
</UserControl>
Then just in any other controls you can reuse this FooUserControl. For example:
<Window x:Class="OpenExcelFileAndConvertToArray.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:OpenExcelFileAndConvertToArray"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel>
<ComboBox Text="qq" Name="comboBox">
<ComboBoxItem Content="1"/>
<ComboBoxItem Content="2"/>
<ComboBoxItem Content="3"/>
</ComboBox>
<!--reusable control-->
<local:FooUserControl/>
</StackPanel>
</Grid>

how do I load an user control in a tabcontrol

I have a user control (UserInfo.xaml) and I want to load this my main tab control.
My goal is to seprate the user control from the tab control.
I cant seem to do this in WPF
My user control looks like this.
<UserControl x:Class="AuthWiz.UserInfo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="750" d:DesignWidth="1000">
<Grid>
<Label Content="Request authorization for New User" HorizontalAlignment="Left" Margin="30,30,0,0" VerticalAlignment="Top" FontSize="20" FontWeight="Bold"/>
</Grid>
I want to load the usercontrol "userinfo" in this Tabcontrol like this.
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:AuthWiz;assembly=AuthWiz" x:Class="AuthWiz.TabControl"
mc:Ignorable="d"
d:DesignHeight="750" d:DesignWidth="1000">
<Grid>
<TabControl HorizontalAlignment="Left" Height="677" Margin="10,63,0,0" VerticalAlignment="Top" Width="980" TabStripPlacement="Top">
<TabItem Header="New User">
<Grid Background="#FFE5E5E5">
<local:UserInfo /> #this does not work.
</Grid>
</TabItem>
</TabControl>
</Grid>
I recieve the following error
The tag 'UserInfo' does not exist in XML namespace 'clr-namespace:AuthWiz;assembly=AuthWiz'.
TabItem can only have one child element, therefore the following is incorrect:
<TabItem Header="New User">
<Grid Background="#FFE5E5E5"/>
<local:UserInfo /> #this does not work.
</TabItem>
Because your TabItem has a Grid, and your UserControl. To solve this problem, simply place your UserControl inside your Grid.
<TabItem Header="New User">
<Grid Background="#FFE5E5E5">
<local:UserInfo />
</Grid>
</TabItem>

Categories