filter xaml gridview with combo box - c#

I am just starting off with windows 8 apps development and I want to be able to filter a gridview using the selected value in a combobox
my xaml page code behind
public sealed partial class MainPage : Page
{
public ObservableCollection<Recording> MyMusic = new ObservableCollection<Recording>();
public MainPage()
{
this.InitializeComponent();
// Add items to the collection.
MyMusic.Add(new Recording("Chris Sells", "Chris Sells Live",
new DateTime(2008, 2, 5)));
MyMusic.Add(new Recording("Luka Abrus",
"The Road to Redmond", new DateTime(2007, 4, 3)));
MyMusic.Add(new Recording("Jim Hance",
"The Best of Jim Hance", new DateTime(2007, 2, 6)));
// Set the data context for the combo box.
//ComboBox1.DataContext = MyMusic;
this.DataContext = new CollectionViewSource { Source = MyMusic };
}
}
Class
public class Recording
{
public Recording() { }
public Recording(string artistName, string cdName, DateTime release)
{
Artist = artistName;
Name = cdName;
ReleaseDate = release;
}
public string Artist { get; set; }
public string Name { get; set; }
public DateTime ReleaseDate { get; set; }
// Override the ToString method.
public override string ToString()
{
return Name + " by " + Artist + ", Released: " + ReleaseDate.ToString("d");
}
}
Xaml mark up
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ComboBox x:Name="ComboBox1" HorizontalAlignment="Left" Margin="542,108,0,0" VerticalAlignment="Top" Width="360" ItemsSource="{Binding}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="2">
<TextBlock Text="Artist:" Margin="2" />
<TextBlock Text="{Binding Artist}" Margin="2" />
<TextBlock Text="CD:" Margin="10,2,0,2" />
<TextBlock Text="{Binding Name}" Margin="2" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!--<StackPanel x:Name="RecordingDetails" Margin="542,150,10,30">
<TextBlock Text="{Binding Artist}" FontWeight="Bold" FontSize="30" />
<TextBlock Text="{Binding Name}" FontStyle="Italic" FontSize="30" />
<TextBlock Text="{Binding ReleaseDate}" FontSize="30" />
</StackPanel>-->
<GridView
x:Name="itemGridView"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Grouped Items"
Grid.RowSpan="2"
Padding="116,137,40,46"
ItemsSource="{Binding}"
SelectionMode="None"
IsSwipeEnabled="false" >
<GridView.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Left" Width="250" Height="250">
<StackPanel VerticalAlignment="Bottom" Background="{ThemeResource ListViewItemOverlayBackgroundThemeBrush}" Name="test">
<TextBlock Text="{Binding Artist}" Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextBlockStyle}" Height="60" Margin="15,0,15,0"/>
<TextBlock Text="{Binding Name}" Foreground="{ThemeResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
<TextBlock Text="{Binding ReleaseDate}" Foreground="{ThemeResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
</StackPanel>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid GroupPadding="0,0,70,0"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
so essentially I just need to filter the gridview dynamically using combo box value selected.
Kindly appreciate help and guidaince please.

This is a msdn example.
You can refer this msdn page link for further details.
UserControl
<UserControl x:Class="TestDataBindingQS.Page2"
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="using:TestDataBindingQS"
mc:Ignorable="d"
d:DesignHeight="768" d:DesignWidth="1366">
<UserControl.Resources>
<local:StringFormatter x:Key="StringConverter"/>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="#FF0C0C0C">
<StackPanel Width="750" Height="200"
VerticalAlignment="Center" HorizontalAlignment="Center">
<ComboBox x:Name="ComboBox1" ItemsSource="{Binding}"
Foreground="Black" FontSize="30" Height="50" Width="750">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="2">
<TextBlock Text="Artist:" Margin="2" />
<TextBlock Text="{Binding Artist}" Margin="2" />
<TextBlock Text="CD:" Margin="10,2,0,2" />
<TextBlock Text="{Binding Name}" Margin="2" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!--The UI for the details view-->
<StackPanel x:Name="RecordingDetails">
<TextBlock Text="{Binding Artist}" FontSize="30" FontWeight="Bold" />
<TextBlock Text="{Binding Name}" FontSize="30" FontStyle="Italic" />
<TextBlock Text="{Binding ReleaseDate,
Converter={StaticResource StringConverter},
ConverterParameter=Released: \{0:d\}}" FontSize="30" />
</StackPanel>
</StackPanel>
</Grid>
</UserControl>
converter class
public class StringFormatter : IValueConverter
{
// This converts the value object to the string to display.
// This will work with most simple types.
public object Convert(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
// Retrieve the format string and use it to format the value.
string formatString = parameter as string;
if (!string.IsNullOrEmpty(formatString))
{
return string.Format(culture, formatString, value);
}
// If the format string is null or empty, simply
// call ToString() on the value.
return value.ToString();
}
// No need to implement converting back on a one-way binding
public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
And this produces the following output

Related

Binding From User Control to User Control - Binding Path Error

I am using a UserControl within a UserControl. Everything works except one piece. I get:
BindingExpression path error: 'SelectedItem' property not found on 'object' ''OrganizationDetailsVM' (HashCode=21529561)'. BindingExpression:Path=SelectedItem; DataItem='OrganizationDetailsVM' (HashCode=21529561); target element is 'ExtendedTreeView' (Name='tvApplications'); target property is 'SelectedItem_' (type 'Object')
Here are the relevant bits:
OrganizationDetailsVM.cs
private AdoptionApplication selectedApplication;
public AdoptionApplication SelectedApplication
{
get { return this.selectedApplication; }
set
{
if (this.selectedApplication != value)
{
this.selectedApplication = value;
RaisePropertyChanged("SelectedApplication");
}
}
}
private object selectedTreeItem;
public object SelectedTreeItem
{
get { return this.selectedTreeItem; }
set
{
if (this.selectedTreeItem != value)
{
this.selectedTreeItem = value;
SelectedApplication = selectedTreeItem as AdoptionApplication;
RaisePropertyChanged("SelectedTreeItem");
RaisePropertyChanged("SelectedApplication");
}
}
}
// other stuff
OrganizationDetails.xaml
<uc:ApplicationsControl x:Name="ucApplications" SelectedItem="{Binding SelectedTreeItem}"
AddApplicationCommand="{Binding AddApplicationCommand}"
EditApplicationCommand="{Binding EditApplicationCommand}"
DeleteApplicationCommand="{Binding DeleteApplicationCommand}"/>
ApplicationsControl.xaml
<UserControl x:Class="CareerChanges.Views.UserControls.ApplicationsControl"
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:cc="clr-namespace:CareerChanges"
xmlns:local="clr-namespace:CareerChanges.Views.UserControls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<cc:SimpleFolderConverter x:Key="folderConverter"/>
</UserControl.Resources>
<Grid Background="#FFE5E5E5"
Loaded="Grid_Loaded">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="419*"/>
<ColumnDefinition Width="75*"/>
</Grid.ColumnDefinitions>
<local:ExtendedTreeView x:Name="tvApplications"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
SelectedItem_="{Binding Path=SelectedItem, Mode=TwoWay, ValidatesOnNotifyDataErrors=True}"
ItemsSource="{Binding AdoptionApplications}">
<local:ExtendedTreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type cc:AdoptionApplication}">
<HierarchicalDataTemplate.ItemsSource>
<MultiBinding Converter="{StaticResource folderConverter}" ConverterParameter=", Breeds, FamilyMembers, Persons">
<Binding Path="Organization"/>
<Binding Path="ApplicationPreferences"/>
<Binding Path="FamilyMembers"/>
<Binding Path="ApplicationPersons"/>
</MultiBinding>
</HierarchicalDataTemplate.ItemsSource>
<StackPanel Orientation="Horizontal" Background="Aquamarine">
<TextBlock Text="Application (" />
<TextBlock Text="{Binding Path=ApplicationID}"/>
<TextBlock Text=") "/>
<TextBlock Text="{Binding Path=Title}" FontStyle="Italic"/>
<TextBlock Text=" "/>
<TextBlock Text="{Binding Path=ApplicationDate, StringFormat=dd-MMM-yyyy}"/>
<TextBlock Text=" "/>
<TextBlock Text="{Binding ApplicationStatusID, Converter={StaticResource ApplicationStatusConverter}}"/>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type cc:ApplicationPreference}" ItemsSource="{Binding Path=Colours}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding BreedID, Converter={StaticResource BreedConverter}}" />
<TextBlock Text=" [" Foreground="Blue" />
<TextBlock Text="{Binding Colours.Count}" Foreground="Blue" />
<TextBlock Text="]" Foreground="Blue" />
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type cc:FolderItem}"
ItemsSource="{Binding Path=Items}">
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="txtName" Text="{Binding Path=Name}" />
<TextBlock Text=" [" Foreground="Blue" />
<TextBlock Text="{Binding Items.Count}" Foreground="Blue" />
<TextBlock Text="]" Foreground="Blue" />
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type cc:Person}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Given}" />
<TextBlock Text=" " />
<TextBlock Text="{Binding Path=Surname}" />
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type cc:FamilyMemberType}">
<TextBlock Text="{Binding Path=FamilyMemberTypeID, Converter={StaticResource FamilyTypeConverter}}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type cc:ColourPreference}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal">
<TextBlock Text="{Binding ColourID, Converter={StaticResource ColourConverter}}" />
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<TextBlock Text=" Male: "/>
<CheckBox IsChecked="{Binding Male}" IsEnabled="False"/>
<TextBlock Text=" Female: "/>
<CheckBox IsChecked="{Binding Female}" IsEnabled="False"/>
</StackPanel>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type cc:Organization}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Organization: " />
<TextBlock Text="{Binding Path=OrganizationName}" />
</StackPanel>
</DataTemplate>
</local:ExtendedTreeView.Resources>
</local:ExtendedTreeView>
<StackPanel Grid.Column="1">
<Button Name="btnAddApplication" Margin="2" Command="{Binding Path=AddApplicationCommand}">Add</Button>
<Button Name="btnEditApplication" Margin="2" Command="{Binding Path=EditApplicationCommand}">Edit</Button>
<Button Name="btnDeleteApplication" Margin="2" Command="{Binding Path=DeleteApplicationCommand}">Delete</Button>
</StackPanel>
</Grid>
</UserControl>
ApplicationsControl.xaml.cs
public object SelectedItem
{
get { return GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
public static readonly DependencyProperty SelectedItemProperty =
DependencyProperty.Register(
"SelectedItem",
typeof(object),
typeof(ApplicationsControl),
new FrameworkPropertyMetadata(
null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
Finally, this is the code for the ExtendedTreeView from this question: Data binding to SelectedItem in a WPF Treeview
ExtendedTreeView.cs
public class ExtendedTreeView : TreeView
{
public ExtendedTreeView()
: base()
{
this.SelectedItemChanged += new RoutedPropertyChangedEventHandler<object>(___ICH);
}
void ___ICH(object sender, RoutedPropertyChangedEventArgs<object> e)
{
if (SelectedItem != null)
{
SetValue(SelectedItem_Property, SelectedItem);
}
}
public object SelectedItem_
{
get { return (object)GetValue(SelectedItem_Property); }
set { SetValue(SelectedItem_Property, value); }
}
public static readonly DependencyProperty SelectedItem_Property = DependencyProperty.Register("SelectedItem_", typeof(object), typeof(ExtendedTreeView), new UIPropertyMetadata(null));
}
For some reason, the binding isn't making it from OrganizationDetailsVM, through OrganizationDetails.xaml to ApplicationsControl.xaml and down to ExtendedTreeview. All the other bindings work perfectly. The tree view does what it should, except for binding to the selected item.
To sum up, I'm having a problem getting from here:
<uc:ApplicationsControl x:Name="ucApplications" SelectedItem="{Binding SelectedTreeItem}"
AddApplicationCommand="{Binding AddApplicationCommand}"
EditApplicationCommand="{Binding EditApplicationCommand}"
DeleteApplicationCommand="{Binding DeleteApplicationCommand}"/>
... to here:
<local:ExtendedTreeView x:Name="tvApplications"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
SelectedItem_="{Binding Path=SelectedItem, Mode=TwoWay, ValidatesOnNotifyDataErrors=True}"
ItemsSource="{Binding AdoptionApplications}">
It boils down to this binding not working:
SelectedItem_="{Binding Path=SelectedItem, Mode=TwoWay, ValidatesOnNotifyDataErrors=True}"
Found it! I'm still new at data binding. After looking at some other code, I modified the binding to:
SelectedItem="{Binding Path=SelectedItem, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:DogPersonsControl}}}">

Could not pass values from view to viewmodel through commands

I am implementing MVVM pattern for my application. I have my Views, ViewModel, Model and Commands and Converters being implemented. Now I am not able to pass my textboxes values from my datatemplate to my ViewModel through the command binding. I am able to click on the button to attempt the update process but its not able to pass the textboxes value. Are there something i need to change on my command class?
Here is my XAML:
<DataGrid AutoGenerateColumns="False" Grid.Row="2" Grid.ColumnSpan="4" Grid.RowSpan="3" x:Name="productionLineConfigDataGrid" Margin="70,0.2,70,0" ItemsSource="{Binding listAllProductionLineConfigs}">
<DataTemplate>
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12" Text="ID: " VerticalAlignment="Center" />
<TextBlock x:Name="txtBlockLineId" FontSize="16" Foreground="MidnightBlue" Text="{Binding ProductionLineId, Mode=TwoWay}" VerticalAlignment="Center" />
</StackPanel>
<StackPanel>
<Button x:Name="btnUpdate" Content="Update" VerticalAlignment="Center" HorizontalAlignment="Right" Click="btnUpdate_Click" Command="{Binding DataContext.updateProductionLineConfigCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:production_line_config_home}}}" CommandParameter="{Binding ProductionLineConfig}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</DataGrid>
Here is the method from my ViewModel:
public ProductionLineConfig ProductionLineConfig
{
get { return productionlineconfig; }
set
{
productionlineconfig = value;
OnPropertyChanged("ProductionLineConfig");
}
}
This is the error message i am getting:
System.Windows.Data Error: 40 : BindingExpression path error: 'ProductionLineConfig' property not found on 'object' ''ProductionLineConfig' (HashCode=47309994)'. BindingExpression:Path=ProductionLineConfig; DataItem='ProductionLineConfig' (HashCode=47309994); target element is 'Button' (Name=''); target property is 'CommandParameter' (type 'Object')
I have included the image for my application here
This is the entire xaml code here and this is the entire viewmodel code here
I'm only going to take a guess at this.
Assuming ProductionLineConfig is what you are binding to for ProductionLineId in the template. Then you probably are just wanting to pass your binding source as the command parameter
CommandParameter="{Binding}"
When {Binding} is empty, it means the Binding is bound to whatever Source there is. Which is also just shorthand for...
{Binding DataContext,RelativeSource={RelativeSource Self}}.
In turn (if the stars align), then it should be your ProductionLineConfig
Based on your code source, I made a sample implementation, to achieve your requirement.
Sample VM:
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
namespace WpfApp5.ViewModels
{
public class ProductionLineConfigViewModel : INotifyPropertyChanged
{
public CustomCommand<ProductionLineConfig> UpdateCommand { get; }
public ProductionLineConfigViewModel()
{
PopulateProductionLineConfigs();
UpdateCommand = new CustomCommand<ProductionLineConfig>(UpdateConfig, (u) => true);
}
private ObservableCollection<ProductionLineConfig> _listAllProductionLineConfigs;
public ObservableCollection<ProductionLineConfig> listAllProductionLineConfigs
{
get { return _listAllProductionLineConfigs; }
set
{
_listAllProductionLineConfigs = value;
OnPropertyChanged();
}
}
// Call this from constructor.
private void PopulateProductionLineConfigs()
{
listAllProductionLineConfigs = new ObservableCollection<ProductionLineConfig>
{
new ProductionLineConfig
{
ProductionLineId = 1,
ProductionLineCode = "001",
ProductionLineCreatedDate = DateTime.Today.Date,
ProductionLineName = "safdsf",
ProductionLineStatus = true
},
new ProductionLineConfig
{
ProductionLineId = 1,
ProductionLineCode = "002",
ProductionLineCreatedDate = DateTime.Today.Date,
ProductionLineName = "sadfadfsdf",
ProductionLineStatus = true
}
};
}
private void UpdateConfig(ProductionLineConfig config)
{
MessageBox.Show("Line Name update: " + config.ProductionLineName);
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class ProductionLineConfig
{
public int ProductionLineId { get; set; }
public string ProductionLineCode { get; set; }
public string ProductionLineName { get; set; }
public bool ProductionLineStatus { get; set; }
public DateTime ProductionLineCreatedDate { get; set; }
}
}
Sample XAML:
<Window x:Name="Root" x:Class="WpfApp5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="clr-namespace:WpfApp5.ViewModels"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<viewModels:ProductionLineConfigViewModel/>
</Window.DataContext>
<Grid Background="#FF006E8C">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Grid.ColumnSpan="4" Content="KAD ShopFloor System" HorizontalAlignment="Center" Margin="10" FontWeight="Bold" FontSize="30" FontFamily="Segoe UI" Foreground="White"/>
<Separator Grid.ColumnSpan="4" Grid.RowSpan="3" Background="White" Margin="0,-35,-0.4,39.2"/>
<DataGrid AutoGenerateColumns="False" Grid.Row="2" Grid.ColumnSpan="4" Grid.RowSpan="3" x:Name="productionLineConfigDataGrid" Margin="70,0.2,70,0"
ItemsSource="{Binding DataContext.listAllProductionLineConfigs, ElementName=Root}">
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Binding="{Binding ProductionLineId, Mode=TwoWay}"/>
<DataGridTextColumn Header="Production Line Code" Binding="{Binding ProductionLineCode, Mode=TwoWay}"/>
<DataGridTextColumn Header="Production Line Name" Binding="{Binding ProductionLineName, Mode=TwoWay}"/>
<DataGridTextColumn Header="Status" Binding="{Binding ProductionLineStatus, Mode=TwoWay}"/>
<DataGridTextColumn Header="Created Date" Binding="{Binding ProductionLineCreatedDate, Mode=TwoWay}"/>
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<Border BorderThickness="0" Background="BlanchedAlmond" Padding="10">
<StackPanel Orientation="Vertical" x:Name="stck">
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12" Text="ID: " VerticalAlignment="Center" />
<TextBlock x:Name="txtBlockLineId" FontSize="16" Foreground="MidnightBlue" Text="{Binding ProductionLineId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12" Text="Line Code: " VerticalAlignment="Center" />
<TextBlock x:Name="txtBlockLineCode" FontSize="16" Foreground="MidnightBlue" Text="{Binding ProductionLineCode, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12" Text="Line Name: " VerticalAlignment="Center" />
<TextBox x:Name="txtLineName" FontSize="16" Foreground="MidnightBlue" Text="{Binding ProductionLineName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
</StackPanel>
<!--<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12" Text="Status: " VerticalAlignment="Center" />
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type DataGrid}},
Path=DataContext.Statusstring}" SelectedValue="{Binding ProductionLineStatus, Converter={StaticResource statusToBooleanConverter}, Mode=TwoWay}" x:Name="cbProductionLineStatus" FlowDirection="LeftToRight" FontSize="16" Foreground="MidnightBlue"
HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
</StackPanel>-->
<StackPanel>
<Button x:Name="btnUpdate" Content="Update" VerticalAlignment="Center" HorizontalAlignment="Right"
Command="{Binding DataContext.UpdateCommand, ElementName=Root}"
CommandParameter="{Binding}" />
</StackPanel>
</StackPanel>
</Border>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</Grid>
</Window>
Sample output:
Key changes here,
You need to change your list to observable collection
Create a custom command that accepts an object, see this post: [UWP/MVVM]Enable/Disable Button in RadDataGrid Data Template Column that have commands bound to them upon conditions
Command Parameter should be the iterated item, can be achieve by CommandParameter={Binding}
In you two way bindings, make sure to add UpdateSourceTrigger=PropertyChanged

wpf help binding data to controls in TabControl

So I have a TabControl with two TabItems, each TabItem has the same controls on it (8 TextBlocks) and will display data under the same bindings as their counterparts on the other TabItem.
The xaml and cs code that I have is below, but when I try execute it I get this error.
Items collection must be empty before using ItemsSource.
XAML for TabItem Structure
<TabControl Name="tbcIndividualStats" HorizontalAlignment="Left" Height="652" VerticalAlignment="Top" Width="1338" ItemsSouce="{Binding tabcontrolitems}">
<!--Template for all tabs (idea is to have them dynamically created eventually)-->
<!--Content template-->
<TabControl.ContentTemplate>
<DataTemplate>
<Grid>
<!--Border just holds the stuff-->
<Border BorderBrush="#FF53535B" BorderThickness="3" HorizontalAlignment="Left" Height="452" VerticalAlignment="Top" Width="520" Margin="10,135,0,0">
<StackPanel Margin="0,0,-1,0">
<TextBlock Name="txtVenue" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding Venue}" />
<TextBlock Name="txtTopSpeed" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding TopSpeed}" />
<TextBlock Name="txtDistRun" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding DistRun}" />
<TextBlock Name="txtTimeLow" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding TimeLow}" />
<TextBlock Name="txtTimeMed" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding TimeMed}" />
<TextBlock Name="txtTimeHigh" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding TimeHigh}" />
<TextBlock Name="txtTimeSprint" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding TimeSprint}" />
<TextBlock Name="txtSprintDist" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding SprintDist}" />
</StackPanel>
</Border>
</Grid>
</DataTemplate>
</TabControl.ContentTemplate>
<!--Item Template-->
<TabControl.ItemTemplate>
<DataTemplate>
<Grid>
<!--Border just holds the stuff-->
<Border BorderBrush="#FF53535B" BorderThickness="3" HorizontalAlignment="Left" Height="452" VerticalAlignment="Top" Width="520" Margin="10,135,0,0">
<StackPanel Margin="0,0,-1,0">
<TextBlock Name="txtVenue" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding Venue}" />
<TextBlock Name="txtTopSpeed" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding TopSpeed}" />
<TextBlock Name="txtDistRun" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding DistRun}" />
<TextBlock Name="txtTimeLow" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding TimeLow}" />
<TextBlock Name="txtTimeMed" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding TimeMed}" />
<TextBlock Name="txtTimeHigh" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding TimeHigh}" />
<TextBlock Name="txtTimeSprint" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding TimeSprint}" />
<TextBlock Name="txtSprintDist" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding SprintDist}" />
</StackPanel>
</Border>
</Grid>
</DataTemplate>
</TabControl.ItemTemplate>
<TabItem Header="PlayerName" Background="Transparent" />
<TabItem Header="PlayerName2" Background="Transparent" />
</TabControl>
C# for Binding Data
public class TabItemContent
{
public string Venue { get; set; }
public string TopSpeed { get; set; }
public string DistRun { get; set; }
public string TimeLow { get; set; }
public string TimeMed { get; set; }
public string TimeHigh { get; set; }
public string TimeSprint { get; set; }
public string DistSprint { get; set; }
}
public void foo()
{
//All one line of code
//FileLoadData is a List of another class where all my data is stored
var tabitemcontents = new List<TabItemContent> { new TabItemContent { Venue = FileLoadData[0].Venue, TopSpeed = FileLoadData[0].TopSpeed.ToString(), DistRun = FileLoadData[0].TotalDistance.ToString(), TimeLow = FileLoadData[0].TimeLow.ToString(),
TimeMed = FileLoadData[0].TimeMed.ToString(), TimeHigh = FileLoadData[0].TimeHigh.ToString(), TimeSprint = FileLoadData[0].TimeSprint.ToString(), DistSprint = "null"},
new TabItemContent { Venue = FileLoadData[1].Venue, TopSpeed = FileLoadData[1].TopSpeed.ToString(), DistRun = FileLoadData[1].TotalDistance.ToString(), TimeLow = FileLoadData[1].TimeLow.ToString(),
TimeMed = FileLoadData[1].TimeMed.ToString(), TimeHigh = FileLoadData[1].TimeHigh.ToString(), TimeSprint = FileLoadData[1].TimeSprint.ToString(), DistSprint = "null"}};
//Error here, supposed to add to the TabItems
tbcIndividualStats.ItemsSource = tabitemcontents;
}
I've been looking for a solution for ages and I can't get one to work. I just need to bind that data from FileLoadData[0] and FileLoadData[1] to the two TabItems respectivly.
I would adopt a different strategy:
Add to your model, the name that you want to show in the Header of the Tabitem:
public class TabItemContent
{
public string PlayerName {get; set;} // New Property for the Tabitem Header
public string Venue { get; set; }
public string TopSpeed { get; set; }
public string DistRun { get; set; }
public string TimeLow { get; set; }
public string TimeMed { get; set; }
public string TimeHigh { get; set; }
public string TimeSprint { get; set; }
public string DistSprint { get; set; }
}
Then i'd change the Xaml considering this new attribute:
<TabControl Name="tbcIndividualStats" HorizontalAlignment="Left" Height="652" VerticalAlignment="Top" Width="1338">
<!--Template for all tabs (idea is to have them dynamically created eventually)-->
<!--Content template-->
<TabControl.ContentTemplate>
<DataTemplate>
<Grid>
<!--Border just holds the stuff-->
<Border BorderBrush="#FF53535B" BorderThickness="3" HorizontalAlignment="Left" Height="452" VerticalAlignment="Top" Width="520" Margin="10,135,0,0">
<StackPanel Margin="0,0,-1,0">
<TextBlock Name="txtVenue" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding Venue}" />
<TextBlock Name="txtTopSpeed" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding TopSpeed}" />
<TextBlock Name="txtDistRun" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding DistRun}" />
<TextBlock Name="txtTimeLow" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding TimeLow}" />
<TextBlock Name="txtTimeMed" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding TimeMed}" />
<TextBlock Name="txtTimeHigh" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding TimeHigh}" />
<TextBlock Name="txtTimeSprint" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding TimeSprint}" />
<TextBlock Name="txtSprintDist" Margin="10,7" FontSize="30" Foreground="White" Text="{Binding SprintDist}" />
</StackPanel>
</Border>
</Grid>
</DataTemplate>
</TabControl.ContentTemplate>
<!--Item Template-->
<TabControl.ItemTemplate>
<DataTemplate>
<Border>
<Textblock = Text="{Binding PlayerName}"/>
</Border>
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
EDIT: the item template is the template for the tabitem button and content template is for its content. Some references here: TabItem.ItemTemplate vs TabItem.ContentTemplate
I've also removed the two TabItem defined inside TabControl.
Remember also to set the ItemsSource -> if you set it in code-behind, remove this line: ItemsSouce="{Binding tabcontrolitems}".
Remove these <TabItem> elements from the XAML:
<TabItem Header="PlayerName" Background="Transparent" />
<TabItem Header="PlayerName2" Background="Transparent" />
You can't both add individual items to the TabControl and use an ItemsSource. It's one way or the other.

Data Binding to a listbox item template not working

I have the following code. It builds and runs but does not populate the listbox. Can someone spot the mistake?
<Grid>
<ListBox ItemsSource="{Binding Path=questions}" Height="401" HorizontalAlignment="Left" Name="results" VerticalAlignment="Top" Width="260" Margin="0,20,0,0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Path=question.votes}" FontSize="15" Padding="5" Background="White" Foreground="Black"/>
<TextBlock Text="{Binding Path=question.answers}" FontSize="15" Padding="5" Background="White" Foreground="Black"/>
</StackPanel>
<StackPanel Orientation="Vertical" Height="Auto" Width="249">
<TextBlock Text="{Binding Path=question.title}" FontWeight="Bold" Background="#FF92F2CD" Height="22" Width="229" Foreground="Black"/>
<TextBlock Text="{Binding Path=question.body}" TextWrapping="Wrap" Height="43" Width="231" Background="#FFEFEFEF" Foreground="Black"/>
</StackPanel>
</StackPanel>
<StackPanel>
<TextBlock Text="{Binding Path=question.tags}" Foreground="#FFFF9C00" Background="#FF4E3D3D" FontWeight="Bold" TextAlignment="Center"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Content="Refresh" Height="22" HorizontalAlignment="Left" Name="button1" VerticalAlignment="Top" Width="54" />
</Grid>
public class question
{
public string votes { get; set; }
public string answers { get; set; }
public string title { get; set; }
public string body { get; set; }
public string tags { get; set; }
}
public partial class MainWindow : Window
{
ObservableCollection<question> questions = new ObservableCollection<question>();
public MainWindow()
{
questions.Add(new question
{
votes = "2",
answers = "3",
title = "This is a sample title",
body = "This is a sample body text. It should wrap and not look like shit when presented.",
tags = "C#,WPF,XML,JediStyle"
});
this.DataContext = this;
InitializeComponent();
}
}
Binding does not work on fields but on properties.
ObservableCollection<question> questions = new ObservableCollection<question>();
ObservableCollection<question> MyQuestions
{
get { return questions; }
}
And in XAML
ItemsSource="{Binding Path=MyQuestions}"
You also don't have to specify question as a part of path for every binding within particular list item:
Text="{Binding Path=question.tags}" should be Text="{Binding Path=tags}" or even simpler: Text="{Binding tags}"
<ListBox ItemsSource="{Binding Path=questions}" Height="401" HorizontalAlignment="Left" Name="results" VerticalAlignment="Top" Width="260" Margin="0,20,0,0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Path=votes}" FontSize="15" Padding="5" Background="White" Foreground="Black"/>
<TextBlock Text="{Binding Path=answers}" FontSize="15" Padding="5" Background="White" Foreground="Black"/>
</StackPanel>
<StackPanel Orientation="Vertical" Height="Auto" Width="249">
<TextBlock Text="{Binding Path=title}" FontWeight="Bold" Background="#FF92F2CD" Height="22" Width="229" Foreground="Black"/>
<TextBlock Text="{Binding Path=body}" TextWrapping="Wrap" Height="43" Width="231" Background="#FFEFEFEF" Foreground="Black"/>
</StackPanel>
</StackPanel>
<StackPanel>
<TextBlock Text="{Binding Path=tags}" //am not sure from where this tags coming
Foreground="#FFFF9C00" Background="#FF4E3D3D" FontWeight="Bold" TextAlignment="Center"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I would try to use a ViewModel ...
Good Article
Another Good Article
The two articles highlight the benefits of full binding and go into the NotifyPropertyChanged and commands. Worth a read.

How to set tooltip with many rows for each (dynamic) listbox item in Silverlight

I would like to set in Silverlight for each item in a ListBox a tooltip with many rows.
In XAML i have a listbox and a button:
<ListBox Height="100" HorizontalAlignment="Left" Margin="24,136,0,0" Name="listBox1" VerticalAlignment="Top" Width="109" ItemsSource="{Binding}">
<Button Content="Add" Name="button_add" VerticalAlignment="Top" Width="118" Click="add_Click">
in c#
private void button_add_Click(object sender, RoutedEventArgs e)
{
ObservableCollection<Person> obs1 = new ObservableCollection<Person>();
obs1.Add(new Person(){Name="Name1", Age=1});
obs1.Add(new Person(){Name="Name2", Age=2});
listBox1.ItemsSource = obs1;
// This Line of Code MUST NOT BE USED!! listBox1.DisplayMemberPath = "Name";
}
public class Person
{
public String Name { get; set; }
public int Age { get; set; }
public override string ToString()
{
return Name;
}
}
I would like to show for each item the Age as my tooltip.
Edit: Ok, this is the Solution for showing only AGE as tooltip. That is one Line/Row.
<ListBox Height="100" HorizontalAlignment="Left" Margin="24,136,0,0" Name="listBox1" VerticalAlignment="Top" Width="109" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" ToolTipService.ToolTip="{Binding Age}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
But what if i want to show a Tooltip with 2 Lines? something like:
Name: Name1
Age: 1
Edit: 3 rows, 2 columns. i also added public String Comment { set; get; } to class Person
<ListBox Height="100" HorizontalAlignment="Left" Margin="24,136,0,0" Name="listBox1" VerticalAlignment="Top" Width="109" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<ToolTipService.ToolTip>
<ToolTip>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="40"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="250"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Name: " Grid.Row="0" Grid.Column="0" />
<TextBlock Text="{Binding Name}" Grid.Row="0" Grid.Column="1"/>
<TextBlock Text="Age: " Grid.Row="1" Grid.Column="0"/>
<TextBlock Text="{Binding Age}" Grid.Row="1" Grid.Column="1"/>
<TextBlock Text="Comment: " Grid.Row="2" Grid.Column="0"/>
<TextBlock Text="{Binding Comment}" Grid.Row="2" Grid.Column="1" TextWrapping="Wrap" />
</Grid>
</ToolTip>
</ToolTipService.ToolTip>
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
But there is stil a problem. The comment can be short or long, so i would like to make the ROWS/LINES/SPACE for Comment to be variable or else Text is cut off.
You can use any controls for tooltip content:
<ToolTipService.ToolTip>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding Age}" />
</StackPanel>
</ToolTipService.ToolTip>
Other possibility would be to use a converter, that returns the Name and Age separated by \r\n.

Categories

Resources