patterncsharpMinor
Resx Editor in WPF
Viewed 0 times
resxwpfeditor
Problem
To aid in the localization of .resx files, I made a generic resx comparer that allows you to edit the values of the resx's. Also, this is my first proper adventure in WPF (I've just been using Windows-runtime before).
This is my view interface:
The view itself:
And the code-behind:
```
public ResxTranslationHelperWindow()
{
InitializeComponent();
}
private void GridDisplay_LoadingRow(object sender, DataGridRowEventArgs e)
{
var item = e.Row.Item as ResxValues;
if (item == null)
{
e.Row.Background = new SolidColorBrush(Colors.White);
return;
}
if (string.IsNullOrEmpty(item.LocalizedValue))
{
e.Row.Background = new SolidColorBrush(Colors.LightSeaGreen);
}
if (string.IsNullOrEmpty(item.Value))
{
e.Row.Background = new SolidColorBrush(Colors.Red);
}
if (!string.IsNullOrEmpty(item.Value) && !string.IsNullOrEmpty(item.LocalizedValue))
{
e.Row.Background = new SolidColorBrush(Colors.White);
}
}
private void DataGrid_BeginningEdit(object sender, DataGridBeginningEditEventArgs e)
{
// keys must not be edited unless they are empty, which signifies adding a new value
if (e.Column.DisplayIndex == 0)
{
var originalText = ((TextBlock) e.EditingEventArgs.OriginalSource).Text;
if (originalText != "")
{
e.Cancel = true;
}
}
}
private void GridDisplay_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
if (e.EditAction == DataGridEditAction.Commit)
{
try
{
OnEndCellEdit(e);
}
catch (ArgumentException)
{
This is my view interface:
public interface IResxTranslationHelperWindow
{
object DataContext { get; set; }
event EventHandler EndCellEdit;
event EventHandler DeleteRow;
void Show();
}The view itself:
And the code-behind:
```
public ResxTranslationHelperWindow()
{
InitializeComponent();
}
private void GridDisplay_LoadingRow(object sender, DataGridRowEventArgs e)
{
var item = e.Row.Item as ResxValues;
if (item == null)
{
e.Row.Background = new SolidColorBrush(Colors.White);
return;
}
if (string.IsNullOrEmpty(item.LocalizedValue))
{
e.Row.Background = new SolidColorBrush(Colors.LightSeaGreen);
}
if (string.IsNullOrEmpty(item.Value))
{
e.Row.Background = new SolidColorBrush(Colors.Red);
}
if (!string.IsNullOrEmpty(item.Value) && !string.IsNullOrEmpty(item.LocalizedValue))
{
e.Row.Background = new SolidColorBrush(Colors.White);
}
}
private void DataGrid_BeginningEdit(object sender, DataGridBeginningEditEventArgs e)
{
// keys must not be edited unless they are empty, which signifies adding a new value
if (e.Column.DisplayIndex == 0)
{
var originalText = ((TextBlock) e.EditingEventArgs.OriginalSource).Text;
if (originalText != "")
{
e.Cancel = true;
}
}
}
private void GridDisplay_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
if (e.EditAction == DataGridEditAction.Commit)
{
try
{
OnEndCellEdit(e);
}
catch (ArgumentException)
{
Solution
I would like to add a few thoughts on WPF part of your code:
-
If you need your buttons to occupy half the screen, you should simply replace
This is not the case where you should use a converter.
-
-
-
-
If you choose to follow the above suggestions, your code behind file will look like this after the refactoring:
-
If you need your buttons to occupy half the screen, you should simply replace
StackPanel with Grid:
This is not the case where you should use a converter.
-
GridDisplay_LoadingRow - now this is a different story. Here converter will fit nicely. You can data bind your data grid item to Background property, and use a converter to set the appropriate Brush depending on item properties. You can use regular converter, or you can use a multibinding. The latter wil update background dynamically, if you implement INotifyPropertyChanged interface on your ResxValues class.-
DataGrid_BeginningEdit - and what if user added a new item but noticed a typo afterwards? Why can't he edit it? He can remove the entire row and re-add it though. Thats a really weird design from UX standpoint. :) If you want to keep this logic, I would suggest using xaml and data binding instead. You can use DataGridTemplateColumn with custom CellEditingTemplate which will be a TextBox for editable cells or TextBlock for read only cells. You will select one or the other by binding to your data grid items. This might be a bit complicated if you've just started learning wpf though.-
GridDisplay_CellEditEnding - so, if user makes a mistake you remove the entire row? :) That's not very user-friendly. I am not sure I understand, why you are recreating ItemsSource either, seems fishy to me (will it update the collection on your viewmodel? or will it break the binding?). WPF have an inbuild system for validating data errors. Normally you would want to let user know, that he made an error (show tooltip, highlight with red border, etc.) and give him a chance to fix it.-
DataGrid_PreviewKeyDown - you should use InputBindings instead.
If you choose to follow the above suggestions, your code behind file will look like this after the refactoring:
public ResxTranslationHelperWindow()
{
InitializeComponent();
}Code Snippets
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<Grid.ColumnDefinitions>
</Grid><DataGrid.InputBindings>
<KeyBinding Key="Delete"
Command="{Binding DeleteCommandOnYourViewModel}"
CommandParameter="{Binding ElementName=YourDataGridName, Path=SelectedItem}"/>
</DataGrid.InputBindings>public ResxTranslationHelperWindow()
{
InitializeComponent();
}Context
StackExchange Code Review Q#94401, answer score: 8
Revisions (0)
No revisions yet.