Binding with Relativesource --wpf - wpf

I have a short question:
I have a datagrid and binded it to something. Then I put a combobox in a column and binded it to another source by
ItemsSource="{Binding DataContext.Users, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}"
Now I want to use datagrid's source again, in the combobox again.That code doesn't work now and I know that there is a ID column in datagrid's source.
SelectedValue="{Binding ID}"
How can I fix it? Thanks in advance.
And here is my whole DataGrid and the problematic part is the combobox.
<DataGrid ItemsSource="{Binding SCs}" SelectedItem="{Binding SelectedSC}" Margin="0,10,0,0"
RowStyle="{StaticResource ResourceKey=DataGridRowStyle}" Style="{DynamicResource ResourceKey=UILDataGridStyle}" AutoGenerateColumns="False" EnableRowVirtualization="True"
RowDetailsVisibilityMode="VisibleWhenSelected" Width="Auto" IsReadOnly="True" Background="Transparent"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch" GridLinesVisibility="Vertical" VerticalGridLinesBrush="{DynamicResource ResourceKey=UILBorderBrush}"
RowHeaderWidth="0" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" BorderBrush="{DynamicResource ResourceKey=UILBorderBrush}"
BorderThickness="1" SelectionUnit="FullRow" SelectionMode="Single" x:Name="SCDataGrid">
<DataGrid.Columns>
<DataGridTextColumn x:Name="securityConfigurationIDColumn" Binding="{Binding Path=SecurityConfigurationID}" Header="Security Configuration ID" Width="*" />
<DataGridTextColumn x:Name="securityConfigurationNameColumn" Binding="{Binding Path=SecurityConfigurationName}" Header="Security Configuration Name" Width="*" />
<DataGridTemplateColumn x:Name="proxyResponsibleUser_IDColumn" Header="Proxy Responsible User ID" Width="*" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox IsEnabled="True" ItemsSource="{Binding DataContext.Users, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}"
SelectedValuePath="{Binding UserID}" DisplayMemberPath="{Binding FullName}" Width="117" Height="20"
SelectedValue="{Binding ProxyResponsibleUser_ID, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ComboBox}}, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn x:Name="responsibleUser_IDColumn" Binding="{Binding Path=User.FullName}" Header="Responsible User ID" Width="*" />
<DataGridTextColumn x:Name="securityConfigurationDescriptionColumn" Binding="{Binding Path=SecurityConfigurationDescription}" Header="Security Configuration Description" Width="*" />
<DataGridTextColumn x:Name="securityConfigurationURLColumn" Binding="{Binding Path=SecurityConfigurationURL}" Header="Security Configuration URL" Width="*" />
</DataGrid.Columns>
</DataGrid>

Use below cell template for combo box.
This code binds entire grid datasource to combo box template, which allow you use any property without doing the jugglery of finding ancestors..
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid DataContext="{Binding }">
<ComboBox IsEnabled="True"
ItemsSource="{Binding Users}"
SelectedValuePath="{Binding UserID}"
DisplayMemberPath="{Binding FullName}"
Width="117" Height="20"
SelectedValue="{Binding ProxyResponsibleUser_ID,
UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>

Related

WPF DataGrid TemplateColumn not switching between edit and normal templates

I have a WPF DataGrid and I am trying to display a TextBlock when not in edit mode and a ComboBox when editing. I would think this would be easy, but it is not. I can only get it to working using a brute force method of placing the controls in a Grid and using a Visibility binding to show the controls in turn; which is a real pain.
Why does the following not work:
I can get one or the other to show, but not both based on cell editing.
<DataGrid Background="DarkGray" ItemsSource="{Binding Items}" CanUserAddRows="false" AutoGenerateColumns="False"
ScrollViewer.CanContentScroll="True" ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
SelectionChanged="DataGrid_SelectionChanged" SelectedIndex="{Binding SelectedIndex}"
behaviors:DataGridBehavior.OnSelectAction="{Binding Path=OnSelectionChanged}">
<DataGrid.Columns>
<DataGridTextColumn Header="Button" Binding="{Binding Button}" />
<DataGridTextColumn Header="Button Display" Binding="{Binding ButtonDisplay}" />
<DataGridTextColumn Header="Reason Code" Binding="{Binding ReasonCode}" />
<!--<DataGridTextColumn Header="Count Stamps" Binding="{Binding CountStamps}" />-->
<DataGridTemplateColumn Header="Count Stamps">
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox IsEditable="True" SelectedValue="{Binding CountStamps}"
ItemsSource="{Binding Values}" DisplayMemberPath="Name" SelectedValuePath="Value" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding CountStamps}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Description" Binding="{Binding Description}" Width="*" />
</DataGrid.Columns>

How to work on control inside Datagrid in WPF?

I m stuck in minor issue,which become time consuming as per my project concern,i am using datagrid in my wpf project in which my requirement is to show payment button only when status is "Not Paid",here i had use DataGridTemplateColumn in which i m using Button and on grid only i m getting status of payment.
Here is my xaml File
<DataGrid Name="gridInvoiceList" SelectedItem="{Binding SelectedDetails}" ColumnHeaderHeight="35" ItemsSource="{Binding ItemsSource, ElementName=pageControl, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" CanUserAddRows="false"
HorizontalAlignment="Left" AutoGenerateColumns="False"
Width="978" RowHeaderWidth="20" RowHeight="25"
CanUserSortColumns="False" SelectionChanged="gridInvoiceList_SelectionChanged" Height="220" LoadingRow="gridInvoiceList_LoadingRow" SelectionMode="Extended" >
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Width="160" Binding="{Binding FullName }" CanUserSort="True" IsReadOnly="True" />
<DataGridTextColumn Header="Total Amount" Width="150" Binding="{Binding TotalAmount,ConverterCulture='en-GB',StringFormat=-{0:C}}" CanUserSort="True" IsReadOnly="True" />
<DataGridTextColumn Header="Invoice Date" Width="200" Binding="{Binding InvoiceDate}" CanUserSort="True" IsReadOnly="True"/>
<DataGridTextColumn Header="Payment Status" Width="220" Binding="{Binding PaymentStatus}" CanUserSort="True" IsReadOnly="True" />
<DataGridTemplateColumn Header="Pay" Width="105">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="Pay" HorizontalAlignment="Center" VerticalAlignment="Top" Name="btnPay" Click="btnPay_Click" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Print" Width="105">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="Print" HorizontalAlignment="Center" VerticalAlignment="Top" Name="btnPrintInvoice" Click="btnPrint_Click" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
I had use some code from reference code which had not fullfill my requirement
You can use a converter to achieve that. But I'll you show you the simplest, easiest way:
Create a property:
public System.Windows.Visibility PayButtonVisibility
{
get
{
if (PaymentStatus == MyEnum.NotPaid)
return System.Windows.Visibility.Visible;
return System.Windows.Visibility.Collapsed;
}
}
Then bind your button visibility to it:
<Button Content="Pay" HorizontalAlignment="Center" VerticalAlignment="Top" Name="btnPay" Click="btnPay_Click" Visibility="{Binding PayButtonVisibility}" />

Add Row to DataGrid if ItemSource Binding returns no data

is there any simple solution to this problem..first i thought i can create an empty ObservableCollection and writte:
ObservableCollection<PersonDetailsView> newOCollection= new ObservableCollection<PersonDetailsView>();
myDataGrid.ItemsSource=newOCollection.ToArray();
and it works..i get an empty row..but the problem is that i loose the other binding..is there any way to Bind to newOCollection only if my {Binding Person} (see the code) doesn't return a value
<DataGrid CanUserAddRows="True" IsReadOnly="False" BorderBrush="#FFCCCCCC"
GridLinesVisibility="All" AutoGenerateColumns="False"
ItemsSource="{Binding Person}" Background="White" Margin="10,45,0,0"
VerticalAlignment="Top" Height="91" HorizontalAlignment="Left"
HeadersVisibility="None" SelectionMode="Single" Name="dtaPersons" Width="415">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Person.Name, Mode=TwoWay}" Width="Auto"/>
<DataGridTextColumn Binding="{Binding Person.Surname, Mode=TwoWay}" Width="*"/>
<DataGridTemplateColumn Width="Auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate >
<Button Style="{DynamicResource ChromelessButtonStyle}" Content="r" FontFamily="Marlett" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
ObservableCollection<PersonDetailsView> newOCollection= new ObservableCollection<PersonDetailsView>();
if (!myDataGrid.Items.Any())
myDataGrid.ItemsSource=newOCollection.ToArray();

WPF databinding a gridview issue

I am working on a dataGrid that is populated from an Entity model. I have the following for the specific column as an attempt to use a combobox during editing and the source for the editing is a CollectionsViewSource.
<Grid DataContext="{StaticResource vsLogins}" Grid.Column="1"
Margin="16,248,154,31">
<DataGrid AutoGenerateColumns="False" EnableRowVirtualization="True"
Height="213" HorizontalAlignment="Left"
ItemsSource="{Binding Source={StaticResource vsLogins}}"
Name="LoginsDataGrid"
RowDetailsVisibilityMode="VisibleWhenSelected"
VerticalAlignment="Top" Width="380"
Background="{StaticResource lgb}" BorderThickness="2"
BorderBrush="#FFFC0303">
<DataGrid.Columns>
<DataGridTextColumn x:Name="LoginNameColumn" Binding="{Binding
Path=LoginName}" Header="Login Name"
Width="200" MinWidth="200" />
<DataGridTextColumn x:Name="PsWrdColumn"
Binding="{Binding Path=PsWrd}"
Header="Password" Width="130" MinWidth="130" />
<DataGridTemplateColumn x:Name="AccessLevelIdColumn" Header="Id"
Width="40" MinWidth="40">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=AccessLevelId}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Source={StaticResource
vsAccessLevels}}" DisplayMemberPath="Description"
SelectedValuePath="AccessLevelId" IsEditable="False"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
It is throwing some errors. What am I doing wrong? I also tried putting a grid around the combobox and setting it's dataContent to the CVS - no dice either. Thanks for any help.
<DataGridComboBoxColumn x:Name="AccessIdColumn"
ItemsSource="{Binding Source={StaticResource vsAccessLevels}}"
DisplayMemberPath="Description"
SelectedValuePath="AccessLevelId"
SelectedValueBinding="{Binding Path=AccessLevelId}"/>

need to select or highlight alike rows in datagrid with RowDetailsTemplate--mvvm

I have datagrid that have rowdetails. My rows can be duplicated. I want to select all rows that are alike. how can I achieve that. I'm using mvvm pattern. I bind the selectedItem to the same property in my view model, but it does not work.
Here's the xaml code:
<DataGrid Margin="0,6,0,12"
BorderBrush="Silver"
SelectionMode="Single"
HeadersVisibility="Column"
AutoGenerateColumns="False"
CanUserAddRows="False"
CanUserDeleteRows="False"
CanUserSortColumns="False"
CanUserReorderColumns="False"
VerticalGridLinesBrush="Silver"
HorizontalGridLinesBrush="Silver"
VerticalScrollBarVisibility="Visible"
HorizontalScrollBarVisibility="Auto"
RowDetailsVisibilityMode="Visible"
IsSynchronizedWithCurrentItem="{x:Null}"
ItemsSource="{Binding AccessoryWalls}"
Grid.Row="1"
Grid.Column="0"
Name="gAccessories">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding ID,StringFormat='W{0}'}" FontWeight="Bold" Foreground="Blue" />
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate >
<DataTemplate>
<Grid >
<DataGrid ItemsSource="{Binding Accessories}"
SelectedItem="{Binding Path=DataContext.SelectedAccessory, RelativeSource={RelativeSource AncestorType={x:Type UserControl}},Mode=TwoWay}"
CanUserAddRows="False"
HeadersVisibility="Column"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Horizontal"
Width="60"
Binding="{Binding Horizontal, Converter={StaticResource DimensionConverter}}" />
<DataGridTextColumn Header="Vertical"
Width="60"
Binding="{Binding Vertical, Converter={StaticResource DimensionConverter}}" />
<DataGridTextColumn Header="Detail"
IsReadOnly="True"
Binding="{Binding LongName}" />
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate />
</DataGrid.RowDetailsTemplate>
</DataGrid>
</Grid>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
As you see I bind it to "SelectedAccessory" on VM level and it works. It synchronizes with other controls in the screen, but it does not synchronizes with other rows in the datagrid.
I would like to select all "Overhead Door Opening12" rows when I clicked on one of them.
Thanks in advance.

Resources