modify Entity framework object before binding to WPF control - wpf

I am new to WPF and entity framework. I have ran into the the following problem while working on an application. In my application I am binding my data using collection view source from entity framework. one of my database table has a column named isNumeric datatype Boolean. if its is true then my grid view in WPF window should show the text "Numeric" and "String" if false. For this requirement I cant directly bind the my linq query result with the grid view or any control in the UI. Any thoughts on how could I solve this.
Here some of my codes
MainWindow.XAML.cs code
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private PartNumbersEntities partNumberContext = new PartNumbersEntities();
private PartNumbersCollection partNumberData;
//private PartClassesCollection partClassData;
private CollectionViewSource MasterViewSource;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//string classFilter = classNameTextBox.Text;
//if (classFilter.Length == 0)
classFilter = "Dis";
//MessageBox.Show(classFilter);
var result = partNumberContext.PartNumbers.Where(p => p.PartClass.chrPCName.Contains(classFilter)).Select(p => p);
this.partNumberData = new PartNumbersCollection(result, partNumberContext);
this.MasterViewSource = (CollectionViewSource)this.FindResource("MasterView");
this.MasterViewSource.Source = this.partNumberData;
}
}
My partNumber Collection
class PartNumbersCollection : ObservableCollection<PartNumber>
{
private PartNumbersEntities _context;
public PartNumbersEntities Context
{
get { return _context; }
}
public PartNumbersCollection(IEnumerable<PartNumber> partNumbers, PartNumbersEntities context)
: base(partNumbers)
{
_context = context;
}
}
Xaml Code
<Window x:Class="Engenious.PartNumbersUI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="454" Width="1033" Loaded="Window_Loaded">
<Window.Resources>
<CollectionViewSource x:Key="MasterView" />
<CollectionViewSource x:Key="PartProperties"
Source="{Binding Source={StaticResource MasterView},
Path='PartProperties'}"/>
<!--<CollectionViewSource x:Key="PartNumberView"
Source="{Binding Source={StaticResource MasterView},
Path='PartNumbers'}"/>-->
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource MasterView}}">
<Grid.RowDefinitions>
<RowDefinition Height="42" />
<RowDefinition Height="310" />
<RowDefinition Height="42" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Name="Grid0">
<StackPanel Name="StackPanel1" Orientation="Horizontal">
<Label Content="Class Filter" Height="28" Name="label1" Margin="3" />
<TextBox Height="28" Name="classNameTextBox" Width="120" Margin="3"/>
<Button Content="Apply" Height="28" Name="applyButton" Width="80" Margin="3"/>
</StackPanel>
</Grid>
<ListView Grid.Row="1" Name="ListView1" VerticalContentAlignment="Top"
VerticalAlignment="Top" HorizontalAlignment="Left" Height="310"
Width="320"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding }">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridViewColumn Header="Part Class Name" Width="150">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Path=PartClass.chrPCName}" Margin="-6,0,-6,0"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Part Number" Width="130">
<GridViewColumn.CellTemplate>
<DataTemplate>
<!--<Label Content="{Binding Source={StaticResource PartNumberView},Path=chrPNPartNumber}" Margin="-6,0,-6,0"/>-->
<Label Content="{Binding Path=chrPNPartNumber}" Margin="-6,0,-6,0"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<ListView Grid.Row="1" Height="310" HorizontalAlignment="Left" Margin="350,0,0,0" Name="listView2"
VerticalAlignment="Top" Width="375"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Source={StaticResource PartProperties}}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridViewColumn Header="Name" Width="150">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Path=ConfigurationProperty.chrCPProperty}" Margin="-6,0,-6,0"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Datatype" Width="130">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Path=ConfigurationProperty.bitCPIsNumeric}" Margin="-6,0,-6,0"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<StackPanel Name="StackPanel4" Orientation="Horizontal" Grid.Row="2">
<Button Height="25" Name="btnAddDetail" Width="82" Margin="3">Save</Button>
<Button Height="26" Name="btnDeleteDetail" Width="83" Margin="3">Delete</Button>
</StackPanel>
</Grid>
Here is a Screen shot

I have used data Trigger to solve this problem..
Here is my XAML for it.
<GridViewColumn Header="Datatype" Width="130">
<GridViewColumn.CellTemplate>
<DataTemplate >
<Label>
<Label.Resources>
<Style TargetType="{x:Type Label}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path = 'ConfigurationProperty.bitCPIsNumeric'}" Value="True">
<Setter Property="Content" Value="Numeric" />
</DataTrigger>
<DataTrigger Binding="{Binding Path = 'ConfigurationProperty.bitCPIsNumeric'}" Value="False">
<Setter Property="Content" Value="String" />
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Resources>
</Label>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>

Related

Getting ContextMenu on DataGrid in WPF/MVVM

UPDATE!!!
I've discovered that even this doesn't work when I put it in the DataGrid:
<DataGrid.ContextMenu>
<ContextMenu >
<MenuItem Header="Add Divider" Click="MenuItem_Click" />
</ContextMenu>
</DataGrid.ContextMenu>
This definitely works in a dummy project set up from scratch. So I don't think I'm having binding problems or datacontext problems.... I'm not getting that far. I suspect that some other part of the program is intercepting and handling the context menu (or right click). I didn't write the original code and it's a large code base. Can someone give me an idea what I should be looking for? What would stop the ContextMenu on the DataGrid from being called. Note that the DataGrid is in a ScrollViewer and StackPanel and the whole control is part of a larger window. In fact, it is one of many tabs.
-END UPDATE
I'm pulling my hair out trying to get a context menu on my DataGrid in my WPF/MVVM project. I post the XAML and ViewModel below. I would like to be able to right click on a row and call a command in the ViewModel that would change one of the column entries for that row.
The XAML (I call out what I think are the key points below)
<UserControl x:Class="Sears.UserInterface.Views.Technician.Alerts.AlertsLogView"
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:Sears.UserInterface.Views.Technician.Alerts"
xmlns:converters="clr-namespace:Common.Controls.Converters;assembly=Common.Controls"
mc:Ignorable="d"
d:DesignHeight="800"
d:DesignWidth="1200">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter" />
</UserControl.Resources>
<StackPanel Orientation="Horizontal">
<ScrollViewer>
<DataGrid Width="1000"
Margin="0"
HorizontalAlignment="Left"
AutoGenerateColumns="False"
Background="Transparent"
DataContext="{Binding}"
HeadersVisibility="Column"
ItemsSource="{Binding Alerts}"
SelectedItem="{Binding SelectedItemProperty, Mode=TwoWay}"
RowBackground="Transparent"
RowHeight="30"
Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType=UserControl}}"
>
**<DataGrid.ContextMenu>
<ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Command="{Binding CloseAlertCommand}" Header="Close Alert"/>
</ContextMenu>
</DataGrid.ContextMenu>**
<DataGrid.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Foreground" Value="Black" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="FontWeight" Value="Bold" />
</Style>
</DataGrid.ColumnHeaderStyle>
<DataGrid.Columns>
<DataGridTemplateColumn Width="*" Header="Id">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding Id}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="TimeStamp">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding AlertTime}" >
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="Severity">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding Severity}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="AlertText">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding AlertText}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="Details">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding Details}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="Active">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding Active}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="Acknowledged">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding Acknowledged}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="Reported">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding Reported}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="Status">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding Status}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="Resolution">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding Resolution}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="Category">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding Category}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</ScrollViewer>
</StackPanel>
Notice the DataGrid.ContextMenu part. I've searched StackOverflow and tried various ideas to get the contextmenu showing up. Nothing. This particular example uses "Tag". I also tried putting the contextmenu in the resources sections as:
<ContextMenu x:Key="DataRowContextMenu" DataContext="{Binding DataContext, RelativeSource={RelativeSource AncestorType=DataGrid, Mode=FindAncestor}}">
<MenuItem x:Name="RowContMenuTransfer" Header="Close Alert" Command="{Binding DataContext.CloseAlertCommand}" CommandParameter="{Binding}" >
</MenuItem>
</ContextMenu>
The "Tag" way of doing it results in no binding errors. You just right click and nothing! Other ways (which I can post) gave binding errors in the output window. Possibly of note is the fact that the DataGrid is inside a ScrollViewer and StackPanel.
Here is the ViewModel
public class AlertsLogViewModel : ViewModelBase, IAlertsLogViewModel, IDisposable
{
private IAlertManager _model;
private readonly object _lock = new object();
private ICommand _closeAlertCommand;
public AlertsLogViewModel(IAlertManager model) : base("AlertsLogViewModel")
{
Alerts = new ObservableCollection<IAlert>();
_model = model ?? throw new ArgumentNullException("model");
_model.AlertStatusUpdated += _model_AlertStatusUpdated;
UpdateAlerts();
}
public IAlert SelectedItemProperty { get; set; }
public ICommand CloseAlertCommand
{
get { return _closeAlertCommand ?? (_closeAlertCommand = new DelegateCommand(CloseAlert)); }
}
private void CloseAlert()
{
_model.CloseAlert(SelectedItemProperty.SystemErrorGuid);
}
public ObservableCollection<IAlert> Alerts { get; private set; }
private void _model_AlertStatusUpdated(object sender, DataAccess.AlertStatusEventArgs e)
{
UpdateAlerts();
}
private void UpdateAlerts()
{
RunOnDispatcher(() =>
{
lock (_lock)
{
var modelAlerts = _model.GetAlerts().OrderBy(p => (int)p.Status).ThenByDescending(p => p.AlertTime);
Alerts.Clear();
if (modelAlerts != null)
{
foreach (var alert in modelAlerts)
{
Alerts.Add(alert);
}
}
}
}
);
NotifyPropertyChanged("Alerts");
}
public void Dispose()
{
if (_model != null)
_model.AlertStatusUpdated -= _model_AlertStatusUpdated;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Note the CloseAlertCommand and SelectedItemProperty. I do see that SelectedItemProperty is being called when I left click, but not right click. CloseAlert is never called.
Finally, in case it's relevant, let me mention that the AlertsLogView is inside a Technicial.xaml page and it is here that it's bound to the ViewModel:
<TabItem Header="Alerts"
PreviewMouseDown="OnPreviewMouseDown"
PreviewTouchDown="OnPreviewTouchDown">
<alertlog:AlertsLogView Margin="5"
DataContext="{Binding AlertsLogViewModel}" />
</TabItem>
Many thanks for any hints, references, pointers or solutions!
-Dave
So, as I have already written in comments, the binding works. I have thought, that you get ContextMenu invoked, but you write you didn't. MouseRightButtonClick can be intercepted by several things:
Implicit or explicit styles for grid or it's parents(If explicit -
comment it out, if implicit - set your own dummy style)
Behaviors for grid or it's parents(comment it out)
Code behind(check, whether there are event handlers in grid or it's parents)
Make it consistently and you will find what is responsible for the issue.

Remove Item in Listview

I am created a listview and add combobox and button control into listview and a button to remove items in this view.I need to remove Listview item when clicking the Remove button inside the listview without clicking the row.
<ListView Name="listView">
<ListView.View>
<GridView>
<GridViewColumn Header="SlNo" Width="40">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox x:Name="txtSlno" Width="35" Text="{Binding slno}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Bar Code" Width="120">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox x:Name="cmbBarcode" IsEditable="True" Width="110" Text="{Binding barcode}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Item Name" Width="250">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox x:Name="txtitemname" IsEditable="True" Width="240" Text="{Binding itemname}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Qty" Width="65">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox x:Name="txtqty" Width="65" Text="{Binding qty}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Unit" Width="65">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox x:Name="txtunit" Width="60" Text="{Binding unit}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Rate" Width="90">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox x:Name="txtrate" Width="85" Text="{Binding rate}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Disc %" Width="80">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox x:Name="txtdiscp" Width="75" Text="{Binding discp}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Disc" Width="80">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox x:Name="txtdisc" Width="75" Text="{Binding disc}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Net Amount" Width="130">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox x:Name="txtnetamount" Width="125" Text="{Binding netamount}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="MRP" Width="130">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox x:Name="txtmrp" Width="125" Text="{Binding mrp}" PreviewKeyDown="txtmrp_PreviewKeyDown"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Remove" Width="70">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button x:Name="btnRemove" Content="Remove" Width="60" BorderThickness="0" CommandParameter="{Binding}" HorizontalContentAlignment="Right" Cursor="Hand" Foreground="Blue" Click="btnEdit_Click"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Border CornerRadius="2" SnapsToDevicePixels="True"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}">
<Border Name="InnerBorder" CornerRadius="1" BorderThickness="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition MaxHeight="11" />
<RowDefinition />
</Grid.RowDefinitions>
<Rectangle Name="UpperHighlight" Visibility="Collapsed" Fill="#75FFFFFF" />
<GridViewRowPresenter Grid.RowSpan="2"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Grid>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="LightBlue"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
The c# code is given below
private void btnEdit_Click(object sender, RoutedEventArgs e)
{
listView.Items.RemoveAt(listView.SelectedIndex);
}
It working properly when first click on listview item and then click the remove button.I need to move item with one click on Remove button
If you are using binding this is how you get the DataContext to remove the row from the source
Button btn = (Button)sender;
SearchItem srchItem = (SearchItem)btn.DataContext;
I used an ICommand instead of button click events since I wanted to put the Command in the parent viewmodel instead of the code-behind, but I'll share anyways since it works for me and could be helpful for you.
Instead of Click="btnEdit_Click", I have Command="{Binding ParentViewModel.btnEditCommand". (I also have CommandParameter="{Binding}" as you do.)
Then in the ParentViewModel, called "MyViewModel":
public ObservableCollection<ListItemsViewModel> ListItems
{
get;
set;
}
public MyViewModel()
{
btnEditCommand = new RelayCommand<object>(btnEditCommand_Do, btnEditCommand_Can);
}
public ICommand btnEditCommand
{
get;
set;
}
public bool btnEditCommand_Can( object param )
{
return true;
}
public void btnEditCommand_Do( object param )
{
ListItems.Remove( param as ListItemsViewModel );
}
and finally, the ListItemsViewModel referenced above inherits from the same parent as MyViewModel inherits from.
Hope this helps.
// Try This Code
String txt = ((TextView)view).getText().toString();
adapter.remove(txt);

WPF Xaml converter Error

I am getting a compilation error as
Error 1 The type or namespace name 'Converters' could not be found (are you missing a using directive or an assembly reference?) G:\C#\Practice\DataGrid\DataGrid\obj\x86\Debug\MainWindow.g.cs 12 7 DataGrid
Below is my Xaml code, I am new to WPF please help me out. I have the converter Class.
<Window x:Class="DataGrid.MainWindow "
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="500" Width="700"
xmlns:c="clr-namespace:Converters">
<Window.Resources>
<c:BoolToStringConverter x:Key="BoolToStringConverter" />
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="59*" />
<RowDefinition Height="402*" />
</Grid.RowDefinitions>
<StackPanel Margin="0,55,0,0" Grid.RowSpan="2">
<DataGrid ItemsSource="{Binding Path=Courses}" AutoGenerateColumns="False" HorizontalAlignment="Left" Name="datagrid1" CanUserAddRows="False" HeadersVisibility="Column" RowDetailsVisibilityMode="Visible" VerticalScrollBarVisibility="Auto" CanUserSortColumns="True" CanUserResizeColumns="False" Height="339" Width="610">
<DataGrid.Resources>
<Style TargetType="{x:Type CheckBox}" x:Key="DataGridCheckBox">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="IsEnabled" Value="True" />
<Setter Property="Margin" Value="4" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Course Title" Width="100">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=Code}" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Course Description" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=Descrption}" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Required" Width="100">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=IsRequired, Converter={StaticResource BoolToStringConverter}}"
VerticalAlignment="Center" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
<StackPanel Margin="0,0,539,32">
<TextBlock Text="Select Enroolment:" FontSize="15"
Height="26"
Grid.RowSpan="1"
Width="134">
</TextBlock>
</StackPanel>
<TextBlock DockPanel.Dock="Left"
HorizontalAlignment="Left"
Text="Select Course:"
Width="139" FontSize="15"
Margin="0,32,0,0">
</TextBlock>
<ComboBox HorizontalAlignment="Right"
Margin="0,0,69,33"
Name="comboBox1"
Width="476"
Height="23"
VerticalAlignment="Bottom" />
</Grid>
xmlns:c="clr-namespace:Converters"
You should check the namespace of your Converters class, that is what you should put in place of Converters. If Converters is your class, then you should put whatever it says after namespace in your .cs file.
Example:
namepsace MyNamespace {
public class Converters { }
}
Then your XAML would be:
xmlns:c="clr-namespace:MyNamespace"
Extra:
If you want to be more specific, you can add the assembly parameter as well.
xmlns:window="clr-namespace:MyNamespace;assembly=MyNamespace"
Where Assembly can be found in your Build Properties (Right-click Project, Properties, Application, Assembly Information)
Your default namespace can also be found in the Build Properties as well.

WPF TextBlock StringFormat Binding To Parent

I have been trying to bind the StringFormat of the Text property of a TextBlock to a templated parent.
Here is where I'm trying to set the StringFormat:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DataFlowControls">
<Style TargetType="{x:Type local:DfcEditTextBox}">
<Setter Property="Margin" Value="-6, 0, -6, 0" />
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:DfcEditTextBox}">
<TextBlock x:Name="PART_TextBlock"
Padding="2, 0, 0, 0"
Text="{Binding Path=Value, StringFormat=ThisStringFormat, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}">
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Here is the parent:
<Window x:Class="DataFlowControls.Show.DfcListView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dfc="clr-namespace:DataFlowControls;assembly=DataFlowControls"
xmlns:local="clr-namespace:DataFlowControls.Show"
Title="DfcListView" Height="400" Width="500">
<Grid>
<StackPanel>
<dfc:DfcListView Name="lvTradesCollection" ItemsSource="{Binding Path=TradesCollection}" KeyboardNavigation.DirectionalNavigation="Continue" >
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.Resources>
<DataTemplate x:Key="Date_DataTemplate">
<dfc:DfcEditTextBox Value="{Binding Path=Date, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}" ThisStringFormat='{}{0:dd/MM/yyyy}' HorizontalContentAlignment="Left" IsEditable="true" />
</DataTemplate>
<DataTemplate x:Key="Asset_DataTemplate">
<dfc:DfcEditTextBox Value="{Binding Path=Asset, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}" HorizontalContentAlignment="Left" IsEditable="true" />
</DataTemplate>
<DataTemplate x:Key="Lots_DataTemplate">
<dfc:DfcEditTextBox Value="{Binding Path=Lots, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}" ThisStringFormat='N2' HorizontalContentAlignment="Center" IsEditable="true" />
</DataTemplate>
<DataTemplate x:Key="Price_DataTemplate">
<dfc:DfcEditTextBox Value="{Binding Path=Price, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}" HorizontalContentAlignment="Center" IsEditable="true" />
</DataTemplate>
<DataTemplate x:Key="IsCheap_DataTemplate">
<dfc:DfcEditCheckBox Value="{Binding Path=IsCheap, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" IsEditable="true" />
</DataTemplate>
<DataTemplate x:Key="NextTrade_DataTemplate">
<dfc:DfcEditComboBox Value="{Binding Path=NextTrade, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{x:Static local:DfcListView.NextTradeTypes}" IsEditable="true" />
</DataTemplate>
</ListView.Resources>
<ListView.View>
<dfc:DfcGridView>
<dfc:DfcGridViewColumn Header="Date" Width="140" CellTemplate="{StaticResource Date_DataTemplate}" />
<dfc:DfcGridViewColumn Header="Asset" Width="40" CellTemplate="{StaticResource Asset_DataTemplate}" />
<dfc:DfcGridViewColumn Header="Lots" Width="40" CellTemplate="{StaticResource Lots_DataTemplate}" />
<dfc:DfcGridViewColumn Header="Price" Width="50" CellTemplate="{StaticResource Price_DataTemplate}" />
<dfc:DfcGridViewColumn Header="IsCheap" Width="60" CellTemplate="{StaticResource IsCheap_DataTemplate}" />
<dfc:DfcGridViewColumn Header="NextTrade" Width="80" CellTemplate="{StaticResource NextTrade_DataTemplate}" />
</dfc:DfcGridView>
</ListView.View>
</dfc:DfcListView>
<Button Content="Add Row" HorizontalAlignment="Left" Margin="5,5,5,5" Click="AddRow_Click"/>
<Button Content="Update Row" HorizontalAlignment="Left" Margin="5,5,5,5" Click="UpdateRow_Click"/>
</StackPanel>
</Grid>
</Window>
Everything works fine until I include the StringFormat=ThisStringFormat, which mucks it up. But I somehow need to connect the StringFormat to the ThisStringFormat property expressed in the parent. I've experimented with changing StringFormat=ThisStringFormat to try to get to the templated parent, but to no avail.
Any ideas on how to solve this one?
The StringFormat property is just a regular property on BindingBase and regular properties cannot be binding targets only dependency properties can. So the answer is: You cannot not do it that way.
Some possible approaches:
Subclass TextBox and add a string format dependency property to which you can bind providing the required functionality
Augment your view model (if you have one) with a FormattedValue property (probably a bit ugly)
Use a MultiBinding for the Text property. One binding goes to Value and one to the ThisStringFormat of the templated parent. Then write a converter implementing IMultiValueConverter to return the formatted value.

Changing ContentTemplate based on ListBox selection

I have a Listbox and a Border in a StackPanel similar to the following:
<StackPanel Orientation="Horizontal">
<ListBox>
<ListBoxItem Content="People"/>
<ListBoxItem Content="Animals"/>
<ListBoxItem Content="Cars"/>
</ListBox>
<Border Width="200>
<ContentPresenter/>
</Border>
</StackPanel>
When selecting an item in the listbox I would like to change the content in the ContentPresenter accordingly e.g. selecting People would change the template to display a series of input fields related to people where as selecting Animals would display a series of fields related to Animals etc. - the behavior of this would be akin to a TabControl.
I think I can achieve this with a DataTrigger which changes the DataTemplate in the Border but I'm not sure how to achieve this.
Any pointers?
Thanks
You can toggle the ContentTemplate using a DataTrigger as follows.
Note, that I am binding an ObservableCollection to a simple object (Thing) with one property called Name, and am I binding the Content of the ContentControl to the SelectedItem in the ListBox using a ViewModel.
<Grid>
<Grid.Resources>
<local:MultiValueConverter x:Key="con" />
<DataTemplate x:Key="PeopleTemplate">
<StackPanel Orientation="Horizontal">
<Label Margin="0,0,5,0" Content="People Name" HorizontalAlignment="Left" Grid.Column="0" />
<TextBox Grid.Column="1" Width="100" Height="25"></TextBox>
<Button Content="OK" Grid.Column="2" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="AnimalsTemplate">
<StackPanel Orientation="Horizontal">
<Label Margin="0,0,5,0" Content="Animal Name" HorizontalAlignment="Left" Grid.Column="0" />
<TextBox Grid.Column="1" Width="100" Height="25"></TextBox>
<Button Content="OK" Grid.Column="2" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="CarsTemplate">
<StackPanel Orientation="Horizontal">
<Label Margin="0,0,5,0" Content="Car Name" HorizontalAlignment="Left" Grid.Column="0" />
<TextBox Grid.Column="1" Width="100" Height="25"></TextBox>
<Button Content="OK" Grid.Column="2" />
</StackPanel>
</DataTemplate>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
<ListBox ItemsSource="{Binding Things}" SelectedItem="{Binding SelectedThing}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0" Orientation="Horizontal">
<TextBlock Padding="5" Text="{Binding Name}" Margin="0"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Border Width="200">
<ContentControl Content="{Binding SelectedThing}">
<ContentControl.ContentTemplate>
<DataTemplate>
<ContentControl Name="cc"
Content="{Binding}"
ContentTemplate="{StaticResource PeopleTemplate}" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=Name}" Value="People">
<Setter TargetName="cc"
Property="ContentTemplate"
Value="{StaticResource PeopleTemplate}" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=Name}" Value="Animals">
<Setter TargetName="cc"
Property="ContentTemplate"
Value="{StaticResource AnimalsTemplate}" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=Name}" Value="Cars">
<Setter TargetName="cc"
Property="ContentTemplate"
Value="{StaticResource CarsTemplate}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>
</Border>
</StackPanel>
<Grid>
Here is the Thing class:
public class Thing
{
public Thing(String name)
{
this.Name = name;
}
public String Name { get; set; }
public static ObservableCollection<Thing> GetThingList()
{
return new ObservableCollection<Thing>(new Thing[3] {
new Thing("People"),
new Thing("Animals"),
new Thing("Cars")
});
}
}

Resources