Using buttons in a DataGridColumn, WPF - wpf

I'm converting a Winforms app to WPF and run in to this error. In the winforms application the system loads buttons into a datagridview. As theres no datagridview in wpf, I've used datagrid. Sadly though, the things dont work. For some odd reason i cannot fix, i cant test what i thought of, i get a weird displayindex error. What i was wondering if someone can tell me either an alternative to what is used in the winforms app or tell me if what i have written works.
Winforms Code:
Dim btn As New DataGridViewButtonColumn()
dgBoorMachine.Columns.Add(btn)
btn.HeaderText = "del"
btn.Text = "X"
btn.Name = "del"
btn.UseColumnTextForButtonValue = True
dgBoorMachine.Columns("del").Width = 30
WPF Code:
<Grid ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="560"/>
<ColumnDefinition Width="425" />
<ColumnDefinition Width="560" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="156" />
<RowDefinition Height="55.2" />
<RowDefinition Height="89.6"/>
<RowDefinition Height="332.8"/>
<RowDefinition Height="217.6"/>
<RowDefinition Height="1" />
<RowDefinition Height="1" />
</Grid.RowDefinitions>
<DataGrid x:Name="dgSlijpMachine" Grid.Row="2" Grid.Column="1">
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button x:Name="btn1" Content="X" Click="btn1_Click"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid>
</Grid>

The error might be because you're missing the <DataGrid.Colums> tag
instead of
<DataGrid x:Name="dgSlijpMachine" Grid.Row="2" Grid.Column="1">
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button x:Name="btn1" Content="X" Click="btn1_Click"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid>
it should be
<DataGrid x:Name="dgSlijpMachine" Grid.Row="2" Grid.Column="1">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button x:Name="btn1" Content="X" Click="btn1_Click"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
Now I don't know exactly what you want to achieve. What this will do, is add a column with a button to every row you add to your DataGrid and nothing else. If you actually want to populate your DataGrid with values, you should bind to the DataGrid's ItemsSource, eg.
<DataGrid x:Name="dgSlijpMachine" Grid.Row="2" Grid.Column="1" ItemsSource="{Binding MyItems}">
where MyItems is an ObservableCollection or similar type.

Related

WPF - Data Grid inside pop up does not show its contents

I have a pop up which contains a data grid. If I divide the data grid into columns, then it shows the columns in the data grid and there is no issue. But when I include some content in the rows in the data grid, then those contents are not visible.
<Popup Name="myPopUp"
Placement="MousePoint"
AllowsTransparency="False"
PopupAnimation="Slide"
StaysOpen="False"
Height="370"
Width="350">
<Border BorderThickness="3" BorderBrush="Black">
<Grid Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="320"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<DataGrid>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Code" Width="160" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="Test"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Border>
</Popup>
I am wondering why it is like that. Can someone help ?
Is that the case that a data grid cannot be included in a pop up ?
To make a popup control visible, you need to set the IsOpen property to true.
For your reference, http://www.c-sharpcorner.com/UploadFile/mahesh/using-xaml-popup-in-wpf/

WPF x:Reference thow Object reference not set to an instance of an object

I am developing an application in WPF and from some reason Visual studio display in error window this exception: Object reference not set to an instance of an object
When I was building application this errors are still visible, but I application works correct
this is a my XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Margin="5"
HorizontalAlignment="Stretch" VerticalAlignment="Top" Orientation="Vertical">
<CheckBox Name="cbPersonType" Content="Person Type" IsChecked="{Binding Path=IsPersonTypeVisible, Mode=TwoWay}" />
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" Margin="5"
HorizontalAlignment="Stretch" VerticalAlignment="Top" Orientation="Vertical">
<DataGrid Name="dgPersons">
<DataGrid.Columns>
<DataGridTextColumn Width="*" Header="Person Type"
Visibility="{Binding Path=IsChecked, Source={x:Reference Name=cbPersonType}, Converter={StaticResource BooleanToVisibilityConverter}}"
/>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
</Grid>
this exception is on DataGridTextColumn.
Does some one know why and what is this error?
This is just a theory from my part trying to explain the errormessage.
Right now I'm struggling with a similar case. However, I have my checkbox in a contextmenu displaying the columns in a datagrid. The user can check the columns he/she wants to see in the datagrid.
Problem is the checkboxes seem not to be initlized until the user actually right-click to open the contextmenu. Until then the datagrid just shows empty rows with no columns at all.
It seems the x:Reference does not kick in until the checkboxes are loaded in the contextmenu.
A simplified XAML of the contextmenu and datagrid is below.
<DataGrid ItemsSource="{Binding OrderCollection}" AutoGenerateColumns="False" IsReadOnly="True" >
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Header="Columnsetup">
<CheckBox x:Name="chkHeadOrderNo" Content="Ordernumber" IsChecked="{Binding columnVisibilityHeadOrderNo}"/>
</MenuItem>
</ContextMenu>
</DataGrid.ContextMenu>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding OrderNo}" Header="Ordernumber"
Visibility="{Binding Source={x:Reference chkHeadOrderNo}, Path=IsChecked, Converter={StaticResource convertVisibility}}"/>
</DataGrid.Columns>
</DataGrid>
I would suggest to replace
Source={x:Reference Name=cbPersonType} with ElementName=cbPersonType. This works fine both in design and runtime modes

user control inside tabitem does not change values

I have a TabContorl and I am adding tabitem dynamically. I have bind datatemplate to some viewmodel and view is loaded as defined in datatemplate.
<DataTemplate DataType="{x:Type viewmodels:ItemViewModel}">
<views:CustomerOrderView />
</DataTemplate>
<DataTemplate DataType="{x:Type viewmodels:InvoiceGeneratorViewModel}">
<views:InvoiceGenerator/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewmodels:OrderDetailsViewModel}">
<views:OrderDetailsView/>
</DataTemplate>
if i use controls directly in customerorderview then it works fine. It means if i switch the tab all values are loaded accordingly but does not work properly when if i use another usercontrol insite customerview user control. I have created once user control have one textbox, button and a popup contorl. When i click on button the popup opens and remains even if swich the tab. If textbox value is change the value is also changed for all tabs. It looks one view is serving all the tabs. I could not understand how to handle it.
Below is the user control which i am using inside customer
<UserControl x:Class="OrderManagement.Views.ProductSelectionView"
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">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="35"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<TextBox x:Name="txtProduct" Grid.Row="0" Grid.Column="0"/>
<Button x:Name="btnSearch" Content="S" Click="OnSearchClick" Grid.Row="0" Grid.Column="1" Margin="5"/>
<Popup x:Name="popup" PlacementTarget="{Binding ElementName=btnSearch}" Placement="Bottom"
Width="300" Height="300" Margin="5">
<Border BorderBrush="Black" BorderThickness="2" Background="AliceBlue">
<Grid >
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="35"/>
</Grid.RowDefinitions>
<DataGrid x:Name="dataGrid" AutoGenerateColumns="False" Grid.Row="0" Grid.ColumnSpan="2"
IsReadOnly="False" CanUserAddRows="False" CanUserDeleteRows="False">
<DataGrid.Columns>
<DataGridCheckBoxColumn Binding="{Binding IsChecked}" IsReadOnly="False"/>
<DataGridTextColumn Header="Product Name" Binding="{Binding Name}"/>
<DataGridTextColumn Header="Quantity In Stock" Binding="{Binding QuantityInStock}"/>
</DataGrid.Columns>
</DataGrid>
<WrapPanel Grid.Row="1" Grid.ColumnSpan="2" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Right">
<Button Content="OK" Click="OnOKClick" Width="80"/>
<Button Content="Cancel" Click="OnCancelClick" Width="80" Margin="20,0,0,0"/>
</WrapPanel>
</Grid>
</Border>
</Popup>
</Grid>
</UserControl>
Tabcontrol virtualize the data as per its datacontext but popup and text value in productselection control remains the same for all tabs. opens the popup but it remains for all the tab.
Let me know if how it can be done or what is the mistake i am doing

How do I get a DataGrid to fill a TabItem

I have the following layout
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="10">
...
</StackPanel>
<TabControl>
<TabItem Header="Summary">
<DataGrid ItemsSource="{Binding SummaryData}"
CanUserAddRows="False"
CanUserDeleteRows="False"
IsReadOnly="True"
HeadersVisibility="Column"
CanUserSortColumns="False" />
</TabItem>
...
</TabControl>
</DockPanel>
Without the DataGrid, the TabControl and TabItems fill the rest of the container perfectly, but when I add the DataGrid it stretches everything out to display all of the rows and columns.
EDIT: more clarity
I am looking to have the DataGrid stretch veritcally and horizontally to fill the TabItem. If it needs more space, I'd like to have the DataGrid's scrollbars appear.
I got the following to do what I want.
<TabItem Header="Summary" >
<Grid x:Name="SummaryGrid">
<DataGrid Height="{Binding ElementName=SummaryGrid, Path=ActualHeight}"
ItemsSource="{Binding SummaryData}"
CanUserAddRows="False"
CanUserDeleteRows="False"
IsReadOnly="True"
HeadersVisibility="Column"
CanUserSortColumns="False" />
</Grid>
</TabItem>
It works until I change the size of the parent panel. The ActualHeight isn't updated. It is good enough for now though.
Is it the kind of behavior you are looking for ?
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="10">
<TextBox Text="tttt" />
</StackPanel>
<TabControl VerticalAlignment="Top" HorizontalAlignment="Left">
<TabItem Header="Summary">
<DataGrid CanUserAddRows="False"
CanUserDeleteRows="False"
IsReadOnly="True"
HeadersVisibility="Column"
CanUserSortColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Column 1" Binding="{Binding}"></DataGridTextColumn>
</DataGrid.Columns>
<sys:String>Entry</sys:String>
</DataGrid>
</TabItem>
</TabControl>
</DockPanel>
By setting those alignments you will have the DataGrid stretch to the available space in the TabItem. but I'm not sure that's exactly waht you are looking for.
You can play with VerticalAlignment and HorizontalAlignment to get exactly what you need. (setting it to Top/Left/Stretch to get only TabItem, or DataGrid or both stretch the way you want)
The accepted answer is a work around...
The tab control will expand within its container along with any tab items. By making a grid its container and specifying row/column to be * sized (expanding within window) that will trickle down to datagrid.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="15"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="15"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="15"/>
<RowDefinition Height="*"/>
<RowDefinition Height="10"/>
<RowDefinition Height="100"/>
<RowDefinition Height="15"/>
</Grid.RowDefinitions>
<TabControl Name="tabOperations"
Grid.Row="1"
Grid.Column="1"
TabStripPlacement="Top"
Margin="0,0,0,4"
>
<TabItem Header="Provider Accounts" >
<DataGrid AutoGenerateColumns="True"
IsReadOnly="True"
ItemsSource="{Binding ProviderAccounts}"/>
</TabItem>
</TabControl>
<GridSplitter Grid.Row="2"
Height="3"
Grid.Column="1"
HorizontalAlignment="Stretch" />
<TextBox Grid.Row="3" Grid.Column="1"
TextWrapping="Wrap" Text="{Binding Status}"
Margin="0,4,0,0"
/>
So regardless of size of the main window, it spans.

How do I create a WPF DataGrid Text + Button Column?

I want a column in my datagrid to display both text and a small ellipsis "..." button - similar to what you see in the Visual Studio property grid. Here is a mockup of the datagrid column I'm trying to build:
When the user clicks the ellipsis button, I will display a custom picker dialog and then in the text section of the column, display what I can of the comma sepatated values (i.e. string) returned from the dialog.
How do I get a datagrid column to contain both text and button as I have mocked up here?
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid.Resources>
<DataTemplate x:Key="mDataTemplate">
<Button Margin="10,10,0,0" >
<Button.Content>
<Grid x:Name="ButtonGrid" Height="Auto" HorizontalAlignment="Left" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock />
<Ellipse />
</Grid>
</Button.Content>
</Button>
</DataTemplate>
</Grid.Resources> </Grid>
You have to use a DataGridTemplateColumn.
Sample code:
<DataGrid>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Your header">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DockPanel>
<Button DockPanel.Dock="Right">...</Button>
<TextBlock Text="{Binding YourProperty}"></TextBlock>
</DockPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>

Resources