i try to show images from database in datagrid that i saved them as binary. pictures are showed but im getting binding errors.
my datagrid xaml codes are:
<DataGridTemplateColumn Header=" Image" Width=" 95">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate >
<Image Source="{Binding ProductImage ,TargetNullValue={x:Null}}" Width=" 80" Height=" 80"></Image>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.HeaderStyle >
<Style TargetType="{x:Type DataGridColumnHeader }">
<Setter Property="FontFamily" Value="Arial Black"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="Foreground" Value="#FF3211B8" />
<Setter Property="FontSize" Value="12"/>
</Style>
</DataGridTemplateColumn.HeaderStyle>
</DataGridTemplateColumn>
and the c# code that im using to convert images to binary and save them to database
FileStream fileStream = new FileStream(FilePath, FileMode.Open, FileAccess.Read);
byte[] ImgByteArr = new byte[fileStream.Length];
fileStream.Read(ImgByteArr, 0, ImgByteArr.Length);
fileStream.Close();
and i send (ImgByteArr) to database
and this is binding errors:
when i scroll up and down, number of binding errors are increasing.
also image can be null.
Related
I have a xaml datagrid containing data, and I am using mvvm.
I would like my cells to change of color after I have edited them. I do not care about saving the color for later use, I just want a visual change right after the content of the cell has been edited.
I was able to achieve the aforementioned behaviour by using a bit of code behind (I wanted to avoid code behind, but since it's purely visual, I guess it's totally fine):
private void MyGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
FrameworkElement element = e.Column.GetCellContent(MyGrid.SelectedItem);
(element.Parent as DataGridCell).Background = (SolidColorBrush)Application.Current.Resources["EditedCellBackground"];
}
This works fine as long as the selected row has the focus. In other words, I can tab back and forth on the same row, and the cell edited has the specified color for background.
Now, the problem is that when I press enter, the row appears to be committed, the cursor moves to the following line, and the background of the edited cell returns back to its original color.
For completeness, here is the datagrid (minus a few columns):
<DataGrid Style="{StaticResource MainContentDataGridTheme}"
ItemsSource="{Binding Source={StaticResource Categories}}"
Grid.Row="1"
x:Name="MyGrid"
CellEditEnding="MyGrid_CellEditEnding">
<DataGrid.GroupStyle>
<GroupStyle>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<DataGridRowsPresenter/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander Name="expander" IsExpanded="True">
<Expander.Header>
<StackPanel>
<TextBlock Text="{Binding Name}" FontWeight="DemiBold" FontSize="13" />
<TextBlock Text="{Binding ItemCount, StringFormat={}Items: {0}}" FontSize="9" />
</StackPanel>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</DataGrid.GroupStyle>
<DataGrid.ColumnHeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Right" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock TextWrapping="WrapWithOverflow" TextTrimming="CharacterEllipsis" Text="{Binding}"></TextBlock>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.ColumnHeaderStyle>
<DataGrid.Columns>
<DataGridTextColumn Width="25*" Binding="{Binding AppliedPercentage, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Header="Applied %">
<DataGridTextColumn.CellStyle>
<Style>
<Setter Property="UIElement.IsEnabled" Value="{Binding IsEnabled}" />
<Setter Property="TextBlock.TextAlignment" Value="Right" />
</Style>
</DataGridTextColumn.CellStyle>
</DataGrid.Columns>
</DataGrid>
Here is the style for the datagrid:
<Style TargetType="DataGrid" x:Key="MainContentDataGridTheme">
<Setter Property="AutoGenerateColumns" Value="False"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="True"/>
<Setter Property="HeadersVisibility" Value="Column"/>
<Setter Property="AlternatingRowBackground" Value="{StaticResource DataGridAlternatingRowColor}" />
<Setter Property="Margin" Value="10,10,10,0" />
<Setter Property="CanUserDeleteRows" Value="False" />
<Setter Property="CanUserAddRows" Value="False" />
<Style.Resources>
<Style TargetType="DataGridCell">
<Style.Setters>
<Setter Property="TextBlock.TextAlignment" Value="Right" />
</Style.Setters>
</Style>
</Style.Resources>
</Style>
How can I keep the background of the edited cell while keeping the behaviour of the enter key? I do not mind losing the row commit (the UpdateSourceTrigger takes care of updating my Properties anyway), but I absolutely want to keep the behaviour of the enter key, that is to say: go to the immediate cell down (next row, same column), and be in a position to edit the content right away.
Thanks
After a bit of research, and experimenting with various things, I finally found a workaround that fulfills my requirements.
I added a bit more code behind to do the following:
Disable the row commit to prevent the background of the edited cell to be reset to its original colour.
Catch the KeyUp Event to artificially recreate the behaviour of the enter key.
So, in the xaml, I added the 2 following properties to my datagrid:
RowEditEnding="MyGrid_RowEditEnding"
KeyUp="MyGrid_KeyUp"
And in the code behind, I implemented the corresponding methods:
private void MyGrid_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
{
// Prevents the row to be committed, but disable the "go to next row" behaviour
e.Cancel = true;
}
private void MyGrid_KeyUp(object sender, KeyEventArgs e)
{
var uiElement = e.OriginalSource as UIElement;
if (e.Key == Key.Enter && uiElement != null)
{
// Handle the key press as normal (-> validate the input)
e.Handled = true;
// Get the next element in the UI
var nextUIElement = uiElement.PredictFocus(FocusNavigationDirection.Down);
// Check if there if the next element is not null. This would occur with the last row of the grid.
if (nextUIElement != null)
{
// Check if the element is a cell, rather than something else like an expander for instance...
if (nextUIElement.GetType().Equals(typeof(DataGridCell)))
{
DataGridCellInfo nextCellInfo = new DataGridCellInfo((DataGridCell)nextUIElement);
// Set the selected row
PrelimsGrid.SelectedItem = nextCellInfo.Item;
// Set the selected cell.
PrelimsGrid.CurrentCell = nextCellInfo;
}
else
{
PrelimsGrid.SelectedItem = uiElement.MoveFocus(new TraversalRequest(FocusNavigationDirection.Down));
}
}
}
}
}
Although this works for me, I would humbly admit that I am not a very experienced developer, and that I would be very happy to read about any improvements or alternative solutions.
All,
I have a WPF datagrid in which there is a template column defined as follows:
<DataGridTemplateColumn Width="105">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="35">
<Button Style="{StaticResource tableButtonStyle}">
<ContentControl/>
</Button>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
The button style (which only displays the button when the user moves the mouse over a specific data grid row) is as follows:
<!-- Disappearing button for tables -->
<Style x:Key="tableButtonStyle" TargetType="Button" BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGridRow}},Path=IsMouseOver}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
I would like to animate the height of the datagrid so that it is 'X' units high when the buttons are hidden, or 'Y' units high when the buttons are displayed. Can this be achieved in the xaml markup?
Thanks in advance!
I don't know if there's a way to do that in XAML(I don't know it because i'm new to xaml).
But what I would do that with code-behind. I would use a fancy animation, something like:
private Storyboard sb=new StoryBoard();
private DoubleAnimation da=new DoubleAnimation();
da.From=datagrid.actualHeight;
da.to=x;
da.Duration = new Duration(TimeSpan.FromSeconds(0.5));
Storyboard.SetTargetProperty(da, new PropertyPath(yourDatagrid.HeigthProperty));
sb.Children.Add(da);
yourDatagrid.BeginStoryboard(sb);
and maybe you can get this inside a ClickEvent.
Hope this help!
here i want to give alternate color white and grey to grid row . i hv done many try but i can not do styling of grid .the code is here
<Style TargetType="{x:Type wpftoolkit:DataGrid}">
<Setter Property="Margin" Value="0" />
<Setter Property="BorderBrush" Value="#A6A6A6" />
<Setter Property="BorderThickness" Value="0,1,0,0"/>
<Setter Property="Background" Value="{StaticResource GridBgBrush}" />
<Setter Property="RowBackground" Value="White" />
<Setter Property="AlternatingRowBackground" Value="#FFF3F6FA" />
<Setter Property="GridLinesVisibility" Value="Horizontal" />
<Setter Property="HorizontalGridLinesBrush" Value="Transparent" />
<Setter Property="RowHeaderWidth" Value="0" />
</Style>
here StaticResource GridBgBrush define earlier on this file as`
plz give proper solution .thanks in advance.
Make sure that your style is either defined within the resources section of your XAML file (after your GridBgBrush, so that it can reference it), or in a ResourceDictionary in your App somewhere making it accessible from anywhere. Without seeing more, I can't tell you where your problem is coming from. That is the correct way to define your style and I have several examples of this working as expected if you're interested in seeing them.
Another thing to note in case you didn't know, is that DataGrid (along with DatePicker) was introduced into WPF v4.0. This makes the WPF Toolkit (at least for the purposes of the DataGrid) unnecessary if you can target that version. After saying that, I suppose there's the slight chance that if you weren't aware you were using one and then styling the other, your style wouldn't work.
<XmlDataProvider x:Key="myData" Source="Data.xml" IsAsynchronous="True" />
<Style TargetType="{x:Type DataGrid}" x:Key="myStyle">
<Setter Property="AlternatingRowBackground" Value="Red"/>
</Style>
<Grid>
<DataGrid ItemsSource="{Binding Source={StaticResource myData}, XPath=persons/person}" AutoGenerateColumns="False" Style="{StaticResource myStyle}">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding XPath=firstname}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding XPath=lastname}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
You need to set AlternationCount property too.
I want to make the data record's VerticalAlignment=Center in DataGrid. By default,the data record's VerticalAlignment=Top, It looks uglily. Can you provide me this style?
I define my style in App.xaml file. The following is my current DataGrid style:
<Style x:Key="DataGridView" TargetType="DataGrid">
<Setter Property="AlternatingRowBackground" Value="AliceBlue"></Setter>
<Setter Property="AlternationCount" Value="1"></Setter>
<Setter Property="AutoGenerateColumns" Value="False"></Setter>
<Setter Property="GridLinesVisibility" Value="Horizontal"></Setter>
<Setter Property="VerticalGridLinesBrush" Value="DarkGray"></Setter>
<Setter Property="HorizontalGridLinesBrush" Value="DarkGray"></Setter>
<Setter Property="RowHeight" Value="32"></Setter>
</Style>
Try setting VerticalContentAlignment="Center" on the DataGrid:
<DataGrid VerticalContentAlignment="Center">
...
</DataGrid>
or you can add a setter to your style:
<Setter Property="VerticalContentAlignment" Value="Center"/>
When applied to ItemsControls, this property usually modifies alignment of each individual item container. In your case, this should make all rows align their contents to center.
UPDATE
Seems like the WPF built-in DataGrid doesn't follow the rule.
The solution depends on the type of the columns you use.
For DataGridTemplateColumn use a CellTemplate like this:
<DataTemplate>
<!--Substitute the TextBlock by the actual cell content, but don't drop VerticalAlignment-->
<TextBlock VerticalAlignment="Center" Text="{Binding Text}"/>
</DataTemplate>
For DataGridTextColumn, set ElementStyle:
<Style>
<Setter Property="FrameworkElement.VerticalAlignment" Value="Center"/>
</Style>
I've tried this on DataGridTextColumn, but the property is from its parent DataGridBoundColumn, so should work for DataGridCheckBoxColumn and DataGridHyperlinkColumn also.
Update 2
BTW, there's another solution.
In my Silverlight 3 user control I am showing a basic DataGrid control. I need to generate the columns programmatically as follows:
Style headerStyle = (Style)Resources["ColumnHeaderStyle"];
DataGridTextColumn col = new DataGridTextColumn();
col.HeaderStyle = headerStyle;
dataGrid.Columns.Add(col);
The style is defined as follows:
<Style x:Name="ColumnStyle" x:Key="ColumnHeaderStyle"
TargetType="prim:DataGridColumnHeader">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Loaded="StackPanel_Loaded">
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding Data}" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
I want to set the data context of the header to a "header" object (with "Name" and "Data" properties which are referenced in the DataTemplate). Unfortunately, I cannot use the StackPanel_Loaded event as suggested elsewhere, because the event handler is also called when the user starts a column drag&drop operation.
What is the correct way of setting the DataContext of a DataGrid column header?
Here's how you would do it in XAML (this works in WPF; not sure if it works in SL)
<DataGridTextColumn Binding="{Binding Path=Discount}">
<DataGridTextColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="Content" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=DataContext.DiscountHeader}" />
</Style>
</DataGridTextColumn.HeaderStyle>
</DataGridTextColumn>
Turns out that one can use the Header property (which is of type Object) as the DataContext for the DataTemplate (set as shown above):
Style headerStyle = (Style)Resources["ColumnHeaderStyle"];
DataGridTextColumn col = new DataGridTextColumn();
col.HeaderStyle = headerStyle;
col.Header = myHeaderDataContext; // DataContext for ColumnHeaderStyle
dataGrid.Columns.Add(col);
Based on Matt's answer, I came up with the solution of binding the header on the DataGridCellsPanel which in Snoop appeared to have the correct data context :
<DataGridTemplateColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource CenterAlignedColumnHeaderStyle}">
<Setter Property="Content" Value="{Binding Path=DataContext.Location, RelativeSource={RelativeSource AncestorType={x:Type DataGridCellsPanel}}}" />
</Style>
</DataGridTemplateColumn.HeaderStyle>
And this is non intrusive in the way that you can still inherits from custom styled headers (see exemple above) or event the base column header style:
<DataGridTemplateColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource {x:Type DataGridColumnHeader}}">
<Setter Property="Content" Value="{Binding Path=DataContext.Location, RelativeSource={RelativeSource AncestorType={x:Type DataGridCellsPanel}}}" />
</Style>
</DataGridTemplateColumn.HeaderStyle>
This solution has the advantage of being pure and clean XAML and to refer to the closest ancestor holding the correct datacontext rather than trying to reach datacontext of top hierarchy elements like UserControl.