Easiest way to bind property from view1 to view2 - c#

View1.xaml
<TabControl x:Name="MainTab">
<TabItem Header="1"></TabItem>
<TabItem Header="2"></TabItem>
View2.xaml
<StatusBar>
<StatusBarItem Content="{Binding ElementName=MainTab, Path=SelectedItem.Header, Mode=OneWay}" />
</StatusBar>
And the Header name of TabItem we can see on StatusBar, it works when both controls are in same view. I guess something is wrong with binding.

Related

xaml inside xaml. How to bind controls

I have xaml inside an xaml. The inside xaml has some bindings which are giving some problems. To explain here is my code
Main xaml
<TabItem Header="Configuration" DataContext="{Binding ComponentsVM}">
<Grid>
<ListBox ItemsSource="{Binding SomeList}" DisplayMemberPath="Name" SelectedItem="{Binding SomeComponent}" SelectedIndex="0"/>
<ig:MyInsideXamlElement Content="{Binding MyUserControl}" DataContext="{Binding}" />
</Grid>
</TabItem>
The inside xaml is
<Grid>
<TextBox Text="{Binding MySearchPath}"/>
</Grid>
The MyUserControl property displays my binding of UserControl without problems. But the MySearchPath property does not get updated with entity framework class. I suspect the binding of my inner xaml(MySearchPath) does not get resolved because the whole tab item's datacontext is ComponentsVM. Is there any way to give a second datacontext to the inner xaml?

Reuse UserControl in TabControl with Various ViewModels

I have one user control that I would like to reuse with multiple ViewModels, all which implement the same interface. I would like to have these embedded in a TabControl.
Currently I can do this for a single instance but I am struggling to reuse my UserControl. For the single instance I can either bind the ViewModel in the UserContol's xaml or instantiate it in the code behind, however I can't figure out how to set this from a higher level.
Here is what I have,
<TabControl HorizontalAlignment="Left" Height="800" Margin="0,0,0,0" VerticalAlignment="Top" Width="600">
<TabItem Header="Tab1">
<Frame Source="SomeUserControl.xaml" BorderThickness="0" Margin="0" />
</TabItem>
</TabControl>
Here is pseudo code for what I would like to achieve,
<TabControl>
<TabItem Header="Tab1">
<Frame Source="{SomeUserControl.xaml, DataContext=ViewModel1}" />
</TabItem>
<TabItem Header="Tab2">
<Frame Source="{SomeUserControl.xaml, DataContext=ViewModel2}" />
</TabItem>
</TabControl>
Thanks!
Instead of hard coding the tabs, bind to an ObservableCollection of an "item" class. I.e. something like
class MyTabItems : INotifyPropertyChanged
{
public string Header...
public object DataContext...
}
create an:
ObservableCollection<MyTabItems>
Bind the TabControl ItemsSource to the ObservableCollection. In the item template for the TabControl bind the Header to the Header property and the DataContext to the DataContext property. The source can be hardcoded in the template or you can add another property to your item class and bind it to that if you want more flexibility.
Thanks to SledgeHammer's answer I was able to take a different approach and get things working.
<TabControl Name="TabControl" ItemsSource="{Binding TabItems}" HorizontalAlignment="Left" Height="800" Margin="0,0,0,0" VerticalAlignment="Top" Width="600">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<UserControl Content="{Binding DataContext}"/>
</DataTemplate>
</TabControl.ContentTemplate>
TabItems was populated in the code behind associated with the xaml above.
this.TabItems = new ObservableCollection<TabItem>
{
new TabItem("Main", new MainControl()),
new TabItem("Tab1", new GenericTabControl(new ViewModel1())),
new TabItem("Tab2", new GenericTabControl(new ViewModel2()))
};

WPF DataTemplate Binding

I discovered when using a ContentTemplate/DataTemplate in a WPF TabControl my Bindings will not work anymore.
I have set up a small example to illustrate:
<Window x:Class="HAND.BindingExample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="BindingExample" Height="506" Width="656"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
>
<Grid>
<TabControl HorizontalAlignment="Left" Height="381" VerticalAlignment="Top" Width="608">
<TabItem Header="TabItem">
<Label Content="{Binding Path=myString}"/>
</TabItem>
<TabItem Header="TabItem">
<TabItem.ContentTemplate>
<DataTemplate>
<Label Content="{Binding Path=myString}"/>
</DataTemplate>
</TabItem.ContentTemplate>
</TabItem>
</TabControl>
</Grid>
</Window>
Tab1 works as expected, Tab2 is empty.
the code behind:
using System.Windows;
namespace HAND
{
public partial class BindingExample : Window
{
public string myString { get; set; }
public BindingExample()
{
myString = "Hello Stackoverflow";
InitializeComponent();
}
}
}
You are using the ContentTemplate property incorrectly. From the ContentControl.ContentTemplate Property page on MSDN:
Gets or sets the data template used to display the content of the ContentControl.
Therefore, when setting this property, you also need to set the Content property to some sort of data source:
<TabControl>
<TabItem Header="TabItem">
<Label Content="{Binding Path=myString}"/>
</TabItem>
<TabItem Header="TabItem" Content="{Binding Path=myString}">
<TabItem.ContentTemplate>
<DataTemplate>
<Label Content="{Binding}" />
</DataTemplate>
</TabItem.ContentTemplate>
</TabItem>
</TabControl>
<TabItem Content="{Binding myString}" Header="TabItem">
<TabItem.ContentTemplate>
<DataTemplate>
<Label Content="{Binding}" />
</DataTemplate>
</TabItem.ContentTemplate>
</TabItem>
But just so you know, to bind a window on itself, is just not the way to go.
I don't know if you did that just for the example, but if not try and create a proper viewModel to bind your window on ;)

C# WPF Set Focus TabItem

I have a TabControl and i want to set the focus on the firsttab on a Textbox.
I tried to use in Code:
this.tabItemMerkmalAllgemein.Focus();
this.textBoxMerkmalBezeichnung.Focus();
If the second tab was selected the first Tab will be selected after this but no Cursor at the Textbox is shown, so the Textbox focus dosen't work.
XAML TabControle:
<TabControl Width="359" Grid.Column="1" Style="{StaticResource EditDialogTabControl}" Name="tabControlMerkmalDetails" Margin="4,0,0,0">
<TabItem Header="Allgemein" Name="tabItemMerkmalAllgemein" GotFocus="tabItemMerkmalAllgemein_GotFocus">
…
<Label Grid.Row="0" Style="{StaticResource EditDialogLabel}" Content="Bezeichnung"/>
<TextBox x:Name="textBoxMerkmalBezeichnung" Grid.Row="0" Grid.Column="1"
Style="{StaticResource EditDialogTextBox}" MaxWidth="300"
Text="{Binding Path=bezeichnung, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
TextChanged="textBoxMerkmalBezeichnung_TextChanged" LostFocus="textBoxMerkmalBezeichnung_LostFocus" />
…
</TabItem>
<TabItem Name="tabItemKostenpflichtig">
…
</TabItem>
</TabControl>
</Grid>
</TabItem>
You need to change your declaration of the TabItem to this:
<TabItem FocusManager.FocusedElement="{Binding ElementName=textBoxMerkmalBezeichnung}"
Header="Allgemein" Name="tabItemMerkmalAllgemein" GotFocus="tabItemMerkmalAllgemein_GotFocus">
The important part is the addition of the FocusManager.FocusedElement attached property. You can find out more from the FocusManager.FocusedElement Attached Property page at MSDN.

WPF Maintain ListBox selection when tab changes

I have a TabControl where the content of each TabItem is a master-details view.
For the master, I'm using a listbox whose ItemsSource is bound to a collection in my ViewModel. Selecting an item from the list displays that particular item's details in a grid off to the side.
When I switch to another tab and then back to the original tab, the listbox selection seems to be lost.
What can I do to maintain the listbox selections in each tab when the tab selection changes?
In normal use the end users will need to 'set up' the detail views the way they like for a particular situation, and then cycle through the tabs occasionally to check on each system (each tab provides details for machinery on a different product line).
The TabControl looks like this:
<TabControl
ItemsSource="{Binding DiagCards}"
ContentTemplate="{StaticResource DiagCardViewTemplate}"
SelectedItem="{Binding SelectedDiagCard}" />
The View for each TabItem has a ListBox that looks like this:
<ListBox
ItemsSource="{Binding DiagCard.DevicesDetected}"
SelectedItem="{Binding SelectedDevice}"/>
The details are displayed in the TabItem using a ContentControl:
<ContentControl
Content="{Binding SelectedDevice}"
ContentTemplateSelector="{StaticResource SelectedDeviceTemplateSelector}"/>
I should note that a simple test using hard-coded TabItems and ListBoxes does seem to maintain the selection when the tab changes:
<TabControl>
<TabItem Header="tab 1">
<ListBox>
<ListBoxItem>
<TextBlock Text="item 1-1"/>
</ListBoxItem>
<ListBoxItem>
<TextBlock Text="item 1-2"/>
</ListBoxItem>
</ListBox>
</TabItem>
<TabItem Header="tab 2">
<ListBox>
<ListBoxItem>
<TextBlock Text="item 2-1"/>
</ListBoxItem>
<ListBoxItem>
<TextBlock Text="item 2-2"/>
</ListBoxItem>
</ListBox>
</TabItem>
</TabControl>
Update: I set IsSynchronizedWithCurrentItem="True" on the listbox and all seems to be well.
Based on your comment I would guess something is changing in your viewmodel to remove the selected item. Can you set a breakpoint on the setter of SelectedDevice and check the call stack?
To test that can you remove the SelectedItem={} code and see if it stays selected when you change tabs?
To answer more completely I would need to see more code.

Categories

Resources