Bound TabControl Repeats Same Content Or Controls Across Tabs - c#

In the example below when data is bound to the tab control, it correctly has the tab headers per the data, but the tab content is always the same; and the last item bound to.
"Frank Wright"'s "Wright" is on every page.
What is wrong? One expects that there are different controls on every page, not one control shared or data repeated.
<Page.Resources>
<model:People x:Key="People">
<model:Person First="Joe"
Last="Smith"
Phone="303-555-5555" />
<model:Person First="Jenny"
Last="Johnson"
Phone="720-867-5309" />
<model:Person First="Frank"
Last="Wright"
Phone="202-555-5555" />
</model:People>
</Page.Resources>
<TabControl ItemsSource="{StaticResource People}">
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Header"
Value="{Binding First}" />
<Setter Property="Content">
<Setter.Value>
<TextBox Text="{Binding Last}" />
</Setter.Value>
</Setter>
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
public class People : List<Person> { }
public class Person
{
public string First { get; set; }
public string Last { get; set; }
public string Phone { get; set; }
}

You want to set the ContentTemplate, not the Content:
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBox Text="{Binding Last}" />
<Label Content="{Binding Phone}" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>

Related

C# SilverLight. The tab key does not change focus for the text boxes

I have got a little problem.
I use ListBox control with the textboxes.
I set focus on the first textbox and try to jump on the following textbox by the key tab.
It does not work.
What do I wrong?
Thanks in advance!
<ListBox Name="Box" ScrollViewer.HorizontalScrollBarVisibility="Disabled" Background="Transparent" BorderThickness="0">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<StackPanel Orientation="Horizontal" Margin="40,2,0,2">
<TextBlock Text="{Binding Label}" MinWidth="20" />
<TextBox TabIndex="{Binding Index, Mode=OneWay}" Text="{Binding Information, Mode=TwoWay}"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
namespace SilverlightApplication1
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
var model = new List<Model>()
{
new Model() {Index = 1, Label = "1"},
new Model() {Index = 2, Label = "2"},
new Model() {Index = 3, Label = "3"},
new Model() {Index = 4, Label = "4"}
};
Box.ItemsSource = model;
}
}
public class Model
{
public int Index { get; set; }
public string Label { get; set; }
public string Information { get; set; }
}
}
You'll need to specify in the style how you want your tabs to work. You shouldn't need to bind the tabindex, unless you want to change up the order the tab works in. I think this should work similar to what you are trying to do:
<ListBox Name="Box"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
Background="Transparent"
BorderThickness="0">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<StackPanel Orientation="Horizontal"
Margin="40,2,0,2">
<TextBlock Text="{Binding Label}"
MinWidth="20" />
<TextBox Text="{Binding Information, Mode=TwoWay}" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="IsTabStop"
Value="False" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.Style>
<Style TargetType="ListBox">
<Setter Property="TabNavigation"
Value="Cycle" />
</Style>
</ListBox.Style>
</ListBox>

Stretch header width in grouped listbox view

How can i stretch the header width in a grouped listbox?
The listbox ItemSource is bound to hierarchical data structure. A group item contains a name and a list of subitems.
public class MyGroup
{
public string GroupName { get; set; }
public ObservableCollection<MyItem> SubItems { get; }
}
public class MyItem
{
public string ItemName { get; set; }
public DateTime Creation { get: set: }
}
public class MyViewModel:
{
public ObservableCollection<MyGroup> Data { get; set; }
}
The page is defined as follows
<Page>
<Page.Resources>
<CollectionViewSource x:Name="cvsListBoxGroup" IsSourceGrouped="True" Source="{Binding Data}" ItemsPath="SubItems"/>
</Page.Resources>
<Page.DataContext>
<local:MyViewModel/>
</Page.DataContext>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ListBox Width="500" SelectionMode="Single" ItemsSource="{Binding Source={StaticResource cvsListBoxGroup}}">
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Grid Background="Beige">
<TextBlock Text="{Binding GroupName}"></TextBlock>
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListBox.GroupStyle>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Background="Bisque">
<TextBlock Text="{Binding ItemName}" Foreground="Black" ></TextBlock>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Page>
Groups and items are displayed. The items don't fill the listbox full width so we need to set the HorizontalContentAlignment for ListBox.ItemContainerStyle. This trick is common - no problem
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListBox.ItemContainerStyle>
I tried to figure out some similiar trick for the groupheader items - but nothing helps.
<GroupStyle.HeaderContainerStyle>
<Style TargetType="GroupItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</GroupStyle.HeaderContainerStyle>
The problem seems the TargetType. For a listview there is a ListViewHeaderItem. But nothing similar exists for the listbox.
See the answer here, it's for ListView but that's basically the same:
https://social.msdn.microsoft.com/Forums/windowsapps/en-US/e8d4f7b3-93a8-4f17-9679-8b700b8d02e6/how-to-adjust-the-width-of-group-header-in-listview-to-stretch-full-width?forum=winappswithcsharp

Combobox SelectedItem change all binded Textboxes in ListView that have the same bind value

So I have a ComboBox in a UserControl. This UserControl is shown when an item is selected from a ListView and is responsible for editing the values of the selected object. The problem is that if I have in the ListView more objects with the same value that the ComboBox is responsible to change, all of this values are change to the value of the selected item in the ListView.
I have this ListView:
<ListView x:Name="AcorduriListView" ItemsSource="{Binding ., UpdateSourceTrigger=PropertyChanged}"
ItemContainerStyle="{StaticResource AcordListViewItem}" />
With this template:
<Style TargetType="ListViewItem" x:Key="AcordListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Grid
d:DataContext="{d:DesignData Source=DesignTimeData/AcordSampleData.xaml, IsDesignTimeCreatable=True}">
...
<TextBlock x:Name="CategorieDescriptionTextBlock" Padding="3,0,0,0" Foreground="Black"
Visibility="{Binding ElementName=CategorieTextBlock, Path=Text, Converter={StaticResource StringNullOrEmptyToVisibilityConverter}}"
Text="Completează categoria" />
<TextBlock x:Name="CategorieTextBlock"
Padding="3,0,0,0" Foreground="Black"
Text="{Binding Categorie.Nume}"
Visibility="{Binding ElementName=CategorieDescriptionTextBlock, Path=IsVisible, Converter={StaticResource InverteBooleanToVisibilityConverter}}" />
...
</StackPanel>
</Border>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="rootPanel" Property="Background"
Value="{StaticResource AccentColorBrush}" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="rootPanel" Property="Background"
Value="{StaticResource AccentColorBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The ListView is bound to a collection of this Object:
public class Acord : INotifyPropertyChanged, IChangeTracking
{
public string Name{ get; set; }
...
public int CategorieId { get; set; }
public virtual Categorie Categorie { get; set; }
}
where Categorie is:
public class Categorie : INotifyPropertyChanged
{
public string Nume { get; set; }
....
private ObservableCollection<Acord> _acorduri;
public virtual ObservableCollection<Acord> Acorduri{ get; set; }
}
When an item from this ListView is Selected, a UserControl is shown based on a trigger on the ListView SelectedIndex. The UserControl has it's DataContext bind to the ListView SelectedItem (an Acord object). From the many controls in this UserControl I have a Combobox CategorieAcordComboBox that has it's ItemsSource bind to a collection of Categorie objects.
<ComboBox Grid.Row="2" Margin="5,0,5,5" x:Name="CategorieAcordComboBox"
DisplayMemberPath="Nume" SelectedValuePath="CategorieId"
Text="{Binding Categorie.Nume}"
IsSynchronizedWithCurrentItem="False" />
<DatePicker Grid.Row="3" Margin="5" FontSize="16" x:Name="DataAcorDatePicker"
controls:TextBoxHelper.Watermark="Data"
SelectedDate="{Binding Data, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Grid.Row="4" x:Name="LocatieAcordTextBox" Margin="5"
controls:TextBoxHelper.UseFloatingWatermark="True"
controls:TextBoxHelper.Watermark="Locație" FontSize="16"
Text="{Binding Locatie, UpdateSourceTrigger=PropertyChanged}" />
My problem is that when I select a diffrent item in ComboBox, while the Text binding is set to Categorie.Nume the content of all the TextBoxes CategorieTextBlock from the template that have the same value, changes to the selected value from ComboBox.
Video: http://screencast.com/t/bbRsb6RMwkZ7

Binding on background color with a custom style on a button and checkbox

I am currently working on a WPF application and have redefined the buttons and checkbox to use a custom style in App.xaml.
App.xaml
<Style x:Key="{x:Type CheckBox}" TargetType="CheckBox">
<Setter Property="Margin" Value="0,0,10,5" />
<Setter Property="Width" Value="85" />
<Setter Property="Height" Value="50" />
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="FocusVisualStyle"
Value="{DynamicResource CheckBoxFocusVisual}" />
<Setter Property="Template" />
<Setter.Value />
<!-- ... etc. -->
</Style>
The code is from here with some modifications.
Now I want to change the background color through coding. For example, if the title of the checkbox is "a" then the background color would be red and so on. I succeeded in binding the titles but not the background color. My checkboxes are used inside a control item.
MainWindow.xaml
<Grid>
<ItemsControl Name="ControllerDisplay">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel HorizontalAlignment="Center"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding controltitle}"
Style="{StaticResource MainControltitle}"/>
<CheckBox>
// want to change checkbox background
<CheckBox.Style>
<Style TargetType="{x:Type CheckBox}"
BasedOn="{StaticResource {x:Type CheckBox}}">
<Setter Property="Background" Value="Aqua" />
</Style>
</CheckBox.Style>
<StackPanel >
<TextBlock Text="{Binding controlno}" HorizontalAlignment="Center"
FontSize="16" />
<TextBlock Text="{Binding status}" HorizontalAlignment="Center"
FontSize="10"/>
</StackPanel>
</CheckBox>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
on the coding side:
public void printcheckbox()
{
List<Controller> listItem = new List<Controller>();
listItem.Add(new Controller() { controltitle = "title1", controlno = "12345",
status = "On" , controlbg = Colors.Red});
ControllerDisplay.ItemsSource = listItem;
}
public class Controller
{
public string controltitle { get; set; }
public string controlno { get; set; }
public string status { get; set; }
public Color controlbg { get; set; }
}

WPF binding multiple UserControls to a listbox

I have multiple UserControls and i want to show them on a ListBox
Lets assume i have an Employee abstract UserControl and i have 2 or more UserControls than use that Employee like AdministrativeEmployee and FactoryEmployee for each of those Employees i have diffrent data but the UserControl is very similar (same size, almost same fields), on the ViewModel side i have an abstract EmployeeViewModel, the AdministrativeEmployeeViewModel and the FatoryEmployeeViewModel, on the EmployeesView i have the ListBox with the databinding and on the EmployeesViewModel i have an ICollection Employees
EmployeesView.xaml:
xmlns:local="clr-namespace:Solution.Controls"
-
<ListBox ItemsSource={Binding Employees}>
<ListBox.ItemTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding}" Name="Presenter" />
<DataTemplate.Triggers>
<DataTrigger Value="{x:Type local:AdministrativeEmployeeView}">
<Setter TargetName="Presenter" Property="Content">
<Setter.Value>
<local:AdministrativeEmployeeView />
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Value="{x:Type local:FactoryEmployeeView}">
<Setter TargetName="Presenter" Property="Content">
<Setter.Value>
<local:FactoryEmployeeView/>
</Setter.Value>
</Setter>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
EmployeesViewModel.cs:
public ICollection<EmployeeViewModel> Employees { get; set; }
But that show me System.ItemTemplate on the ListBox and not the UserControls for each type of Employee
In ListBox resources define two DataTemplates:
<ListBox ItemsSource="{Binding Employees}">
<ListBox.Resources>
<DataTemplate DataType="{x:Type local:AdministrativeEmployee}">
<local:AdministrativeEmployeeView />
</DataTemplate>
<DataTemplate DataType="{x:Type local:FactoryEmployee}">
<local:FactoryEmployeeView />
</DataTemplate>
</ListBox.Resources>
</ListBox>
Model classes:
public class Employee
{
public string Name { get; set; }
}
public class AdministrativeEmployee : Employee
{
}
public class FactoryEmployee : Employee
{
}
Sample data:
List<Employee> _source = new List<Employee>();
_source.Add(new AdministrativeEmployee { Name = "A test1" });
_source.Add(new FactoryEmployee { Name = "F test1" });
_source.Add(new AdministrativeEmployee { Name = "A test2" });
_source.Add(new FactoryEmployee { Name = "F test2" });
Employees = _source;
AdministrativeEmployeeView:
<UserControl ...>
<Grid>
<TextBlock Text="{Binding Name}" Background="Red" />
</Grid>
</UserControl>
FactoryEmployeeView:
<UserControl ...>
<Grid>
<TextBlock Text="{Binding Name}" Background="Green" />
</Grid>
</UserControl>
Result:

Categories

Resources