How to call a window using tabcontrol in wpf - wpf

I have a Main_window which runs as base.
It has some buttons on its left side.
If button1 is clicked, I need a window ( which is defined separately as login) to open as a Tabcontrol in my Main_window (located at center).
So each time when I click one of the buttons, the corresponding windows should be shown as tabs in the main window.
Hoping for the right answer...
Thank You.

Try this
XAML:
<Window x:Class="Test1.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.ColumnDefinitions>
<ColumnDefinition Width="134*" />
<ColumnDefinition Width="369*" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Button Content="Login" Height="23" HorizontalAlignment="Left" Margin="24,28,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
</Grid>
<Grid Grid.Column="1">
<TabControl Name="TabControl"/>
</Grid>
</Grid>
</Window>
C#:
namespace Test1
{
/// <summary>
/// Interaktionslogik für MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
TabItem item = new TabItem();
item.Header = "Some header";
//item.Content = < your content>
TabControl.Items.Add(item);
}
}
}

Related

Binding text property of text box to variable defined on MainWindow-WPF

I'm newbie on WPF and I have text box and button which open folder browser dialog.
When the user select folder I would like text box will contain the selected path.
So on MainWindow I added two variables:
public partial class MainWindow : Window
{
public string outputFolderPath { get; set; }
string reducedModelFolderPath { get; set; }
}
and when user selected folder path (after open folder dialog) I updated those variables by doing (for example):
outputFolderPath = dialog.SelectedPath
In MainWindow.xaml:
<TextBox x:Name="outputFolder" Width ="200" Height="30" Grid.Row="1" Grid.Column="1" Margin="5 10">
How can I bind TextBox.Text to outputFolderPath variable?
Thanks for your assitance!
You need to set DataContext of your window to this, to access your property in XAML, and after that bind to the property. As you are binding not to DependencyProperty, you should notify your binding that property has changed, which could be done by implementing INotifyPropertyChanged interface in your Window.
I've provided sample code to show the concept.
But this is very ugly, much better to use MVVM pattern instead.
MainWindow.xaml.cs
public partial class MainWindow : Window, INotifyPropertyChanged
{
public string outputFolderPath { get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
public event PropertyChangedEventHandler PropertyChanged;
private void Button_Click(object sender, RoutedEventArgs e)
{
outputFolderPath = "Some data";
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(outputFolderPath)));
}
}
MainWindow.xaml
<Window x:Class="simplest.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:simplest"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Button Click="Button_Click" Content="Go" />
<TextBox x:Name="outputFolder" Width ="200" Height="30" Grid.Row="1" Grid.Column="1" Margin="5 10" Text="{Binding outputFolderPath}"/>
</Grid>
</Window>

wpf how to change a canvas image Position programmatically

I am a student on my final year and im doing a project regarding WPF but i'm totally new to WPF and i have been assigned some tasks,but im currently stuck on how to change the Image position on the canvas programitically from left to right.below are the codes
<<Window x:Class="changing_bird_position.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<Canvas Name="canvas" Background="LightBlue" Width="500" Height="280" Margin="264,0,28,0">
<Image Source="inlandbird.png" Name="Image" Height="43" Canvas.Left="55" Canvas.Top="22"/>
</Canvas>
<Button Content="Button" Click="Button_Click" Width="50" Height="50" Margin="246,0"/>
</StackPanel>
Xaml.cs
public partial class MainWindow : Window
{
Image img = new Image();
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Canvas.SetLeft(img, 200.0);
Canvas.SetTop(img, 200.0);
In your code behind you don't need to create this instance of an Image (img). You can access the image by it's name property.
I renamed the image in the xaml to make it clear.
XAML:
<Window x:Class="WpfApplication15.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<Canvas Name="canvas" Background="LightBlue" Width="500" Height="280" Margin="264,0,28,0">
<Image Source="inlandbird.png" Name="BirdImage" Height="43" Canvas.Left="55" Canvas.Top="22"/>
</Canvas>
<Button Content="Button" Click="Button_Click" Width="50" Height="50" Margin="246,0"/>
</StackPanel>
</Window>
Code behind:
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Canvas.SetLeft(BirdImage, 200.0);
Canvas.SetTop(BirdImage, 200.0);
}
}
}

Binding to a property of a borders child

I have implemented my own simple version of a navigation window, mainly because navigation windows journal does not give me control over how many children can exist. So I am using a border inside a window and changig its child everytime. As children I am using a UserControl. I want to bind the title of my Window to the Title property of my current child. Somehow I cannot figure out a way to do it.
MainWindow XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="525"
Height="350"
Background="AliceBlue"
Title="{Binding Path=Child.Title,
ElementName=borderContent}">
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<Button Content="<-" x:Name="btnBack" />
<Button Content="->" x:Name="btnForward" />
</StackPanel>
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<Button Content="1" Click="Button_Click_1" />
<Button Content="2" Click="Button_Click_2" />
</StackPanel>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Border x:Name="borderContent" />
</ScrollViewer>
</DockPanel>
MainWindow Code behind:
using System;
using System.Windows;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
this.borderContent.Child = new ContentPage("Title 1");
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
this.borderContent.Child = new ContentPage("TITLE 2");
}
}
}
UserControl XAML:
<UserControl x:Class="WpfApplication1.ContentPage"
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="300" d:DesignWidth="300">
<Grid>
<TextBlock Text="{Binding Source={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=Title}" />
</Grid>
User Control Code behind:
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for Content.xaml
/// </summary>
public partial class ContentPage : UserControl
{
public string Title
{
get { return (string)this.GetValue(ContentPage.TitleProperty); }
set { this.SetValue(ContentPage.TitleProperty, value); }
}
// Using a DependencyProperty as the backing store for Title. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(string), typeof(ContentPage), new UIPropertyMetadata(string.Empty));
public ContentPage(string Title)
{
this.Title = Title;
InitializeComponent();
}
}
}
Somehow the binding inside the UserControl is also not working. What am I doing wrong?
The problem is that the Child property of a Borderisn't a DependencyProperty so there is no change notification. You'll have to update the Binding manually everytime you change the Child
private void Button_Click_1(object sender, RoutedEventArgs e)
{
this.borderContent.Child = new ContentPage("Title 1");
UpdateTitleBindingExpression();
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
this.borderContent.Child = new ContentPage("TITLE 2");
UpdateTitleBindingExpression();
}
private void UpdateTitleBindingExpression()
{
BindingExpressionBase beb = BindingOperations.GetBindingExpressionBase(this, Window.TitleProperty);
if (beb != null)
{
beb.UpdateTarget();
}
}
I'm not sure why you are doing what you are doing, but regarding your question:
change "Source" to "RelativeSource"
<Grid>
<TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=Title}" />
</Grid>
That should fix the binding issue
Edit:
When you really want to do it that way, you could make the borderContent element an ContentControl and use the Content property instead. Since this is an DependencyProperty you're binding will work:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="525"
Height="350"
Background="AliceBlue"
Title="{Binding Content.Title, ElementName=borderContent}">
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<Button Content="<-" x:Name="btnBack" />
<Button Content="->" x:Name="btnForward" />
</StackPanel>
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<Button Content="1" Click="Button_Click_1" />
<Button Content="2" Click="Button_Click_2" />
</StackPanel>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<ContentControl x:Name="borderContent" />
</ScrollViewer>
</DockPanel>
</Window>

How to show a warning window before opening a combobox items list?

My requirement is to show a warning window (in some specific conditions) when clicking on a WPF combobox, just before it shows a list of available items to choose from. The window asks the user if he proceeds or not.
The problem is that after showing this warning window, the combobox popup that should appear to select an item is not open, no matter if I set the property IsDropDownOpen to do so. See the code for details.
<Window x:Class="ComboBoxTester.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">
<StackPanel>
<ComboBox Height="20" PreviewMouseDown="ComboBox_PreviewMouseDown">
<ComboBoxItem>Item 1</ComboBoxItem>
<ComboBoxItem>Item 2</ComboBoxItem>
<ComboBoxItem>Item 3</ComboBoxItem>
</ComboBox>
<CheckBox x:Name="warningConditionCheckBox" >Is warning condition?</CheckBox>
</StackPanel>
</Window>
and the code behind contains:
namespace ComboBoxTester {
using System.Windows.Input;
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
}
private void ComboBox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (warningConditionCheckBox.IsChecked == true)
{
// Warn about this situation
var window = new MyDialog { Owner = GetWindow(this) };
// Confirm to proceed
if (window.ShowDialog() != true) {
e.Handled = true;
}
else {
comboBox.IsDropDownOpen = true;
}
}
}
}
}
MyDialog is just a Dialog Window:
<Window x:Class="ComboBoxTester.MyDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MyDialog" Height="150" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<Border Background="Silver">
<TextBlock Text="Warning! Sure to proceed?" TextAlignment="Center"/>
</Border>
<StackPanel Grid.Row="1">
<Button Width="100" Content="OK" IsDefault="True" Click="ButtonOkClick"/>
<Button Width="100" Content="Cancel" IsCancel="True"/>
</StackPanel>
</Grid>
</Window>
namespace ComboBoxTester {
using System.Windows;
/// <summary>
/// Interaction logic for MyDialog.xaml
/// </summary>
public partial class MyDialog
{
public MyDialog()
{
InitializeComponent();
}
private void ButtonOkClick(object sender, RoutedEventArgs e)
{
DialogResult = true;
}
}
}
My idea is to use the WPF combobox to deal with this requirement. And to not create another control, if this is possible. So... How can I see the list of items from this combobox after showing a window? Any suggestion helps.
This is often an issue in WPF that while you are in an event handler you can set other UI controls' properties but they are not processed properly.
But you can invoke your change via the dispatcher, which will queue your request in the UI Message Queue, where it is properly processed after your event handler:
Instead of
comboBox.IsDropDownOpen = true;
use:
Action action = () => comboBox.IsDropDownOpen = true;
Application.Current.Dispatcher.BeginInvoke(action);

TabControl doesn't show the tab collection

I'm trying to build a very simple and basic application that adds tab items to tab control using the MVVM pattern.
So i created:
a simple view with one button - "CustomerView.xaml"
an empty ViewModel class - it is empty cause the view doesn't save or extract any information from the Viewmodal (have only one button) - "CustomerViewModel.cs"
The MainWindow class code holds an observable collection of the CustomerViewModel
and have one "Add customer" button - to add a customer tab item to the tabcontrol and the tabcontrol itself.
i don't use commands cause it is not relevant at this time , i just was the new tabitem to appear when i add a new CustomerViewModel to the collection.
the result is that , although i can see that CustomerViewModels are added to the Observable collection, i still don't see tabitems added to the tabcontrol - The collection is not updating the the tabcontrol.
This is the MainWindow XAML:
<Window x:Class="MyViewModalTabControl.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:MyViewModalTabControl.ViewModal"
xmlns:vw="clr-namespace:MyViewModalTabControl.Views"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate DataType="{x:Type vm:CustomerViewModel}">
<vw:CustTabView />
</DataTemplate>
<DataTemplate x:Key="ClosableTabItemTemplate">
<DockPanel Width="120">
<Button
Content="X"
Cursor="Hand"
DockPanel.Dock="Right"
Focusable="False"
FontFamily="Courier"
FontSize="9"
FontWeight="Bold"
Margin="0,1,0,0"
Padding="0"
VerticalContentAlignment="Bottom"
Width="16" Height="16"
/>
<ContentPresenter
Content="Sample"
VerticalAlignment="Center"
/>
</DockPanel>
</DataTemplate>
</Window.Resources>
<Grid Margin="4" ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Name="CustTabButton" Content="New Customer" Height="30" Margin="12,136,9,136" Click="CustTabButton_Click"></Button>
<TabControl Grid.Column="1" Grid.Row="0" Background="Red"
ItemsSource="{Binding CustomerTabs}"
ItemTemplate="{StaticResource ClosableTabItemTemplate}"
>
</TabControl>
</Grid>
This is the code behind of the MainWindow:
public partial class MainWindow : Window
{
private ObservableCollection<CustomerViewModel> _customertabs;
public ObservableCollection<CustomerViewModel> CustomerTabs
{
get
{
if (_customertabs == null)
{
_customertabs = new ObservableCollection<CustomerViewModel>();
// _workspaces.CollectionChanged += this.OnWorkspacesChanged;
}
return _customertabs;
}
}
public MainWindow()
{
InitializeComponent();
}
private void CustTabButton_Click(object sender, RoutedEventArgs e)
{
CustomerViewModel CustomerWorkSpace = new CustomerViewModel();
this.CustomerTabs.Add(CustomerWorkSpace);
}
}
This is the Viewmodel class:
public class CustomerViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
}
This is the View :
UserControl x:Class="MyViewModalTabControl.Views.CustTabView"
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="300" d:DesignWidth="300">
<Grid>
<Button Name="CustTabButton" Content="New Customer" Height="30" Margin="12,136,9,136"></Button>
</Grid>
What am i missing ?
where do you set the datacontext for your mainwindow? Your bindings will just work with the right Datacontext.
and wouldn't it be better to create a mainviewmodel too, which handles the stuff you put in the mainwindow.cs at the moment?
EDIT: pls look at this msdn post from josh smith. there you can find a closable tab too.
Try any of the following
the ClosableTabItemTemplate should "return" TabItem that will be displayed in the Tab control not the DockPanel
create template for the TabItem control
do it in code
This is the fix:
public MainWindow()
{
InitializeComponent();
this.DataContext=this;
}

Resources