Selecting same item in 2 different Grid-Views - wpf

I have 2 RadGridView.
GridView 1: short list has items from GridView2.
GridView 2: Long list has telerik:RadGridView.GroupDescriptors for group the items.
I want if I select one row in first GridView takes me to the same Row in the second GridView.
So, I put in Xaml
//XAML
SelectedItem="{Binding SelectedDP}" For GridView1
SelectedItem="{Binding SelectedDP1}" For GridView2
//CS
private DataPermission mSelectedDP = new DataPermission();
public DataPermission SelectedDP
{
get { return mSelectedDP; }
set
{
mSelectedDP = value;
foreach (SecurityDataPermissions m in DisplayedDataPermissionsList)
{
if (m.DataPermission.DataPointName == SelectedDP.DataPointName)
SelectedDP1 = m;
}
OnPropertyChanged("SelectedDP");
}
}
private SecurityDataPermissions mSelectedDP1 = new SecurityDataPermissions();
public SecurityDataPermissions SelectedDP1
{
get { return mSelectedDP1; }
set
{
this.mSelectedDP1 = value;
OnPropertyChanged("SelectedDP1");
}
}
The row in GridView2 is getting selected but it doesn't scroll to it. I mean if manually scrolled to the item I can see it gray (selected but not focused) but If not, I can't recognize which row is selected.
What I want is when I select row in GridView1 takes me to the same row in GridView2

You could handle the SelectionChanged event and call the ScrollIntoViewAsync method in the event handler as suggested in the official documentation.
private void gridView_SelectionChanged(object sender, Telerik.Windows.Controls.SelectionChangeEventArgs e)
{
gridView.ScrollIntoViewAsync(gridView.SelectedItem, radgridView.Columns[0]);
}
You may of course wrap this functionality in an attached behaviour if you want to: https://www.telerik.com/forums/auto-scroll-to-the-selected-item

Related

datagrid datatable binding and setting specific cell's tooltip and background color

I have a DataGrid bound to a DataTable, with autogeneratecolumns=true because the datatable can be anything from Excel's files.
But now I want to paint specific cells with red and add a tooltip which is an error message that can be appear in the validation process when the data is loaded from Excel.
My goal is Paint in red all the cells with errors. The errors are in a List<CError> where CError may have data like {row=4,col=6,Error=" the date is wrong"} so some cells will have error, and I want to Paint those cells with red and attach to them the error in the tooltip, but I can not find the way. My DataGrid is defined like:
in the Viewmodel I have the "LoadData()" method which runs when some button is pressed, that function is:
public List<CError> ErrorInSheet {get;set;}
public void LoadData()
{
Sheets= GetSheetsFromExcel(PathExcel);
SelectedSheet= Sheets.FirstOrDefault();
MyDataTableFromExcel= LoadDataFromSheet(PathExcel, SelectedSheet);
ErrorInSheet=ValidateData(MyDataTableFromExcel);
}
and the CError class is this:
public class CErrorExcel
{
public int row { get; set; }
public int col { get; set; }
public string Error { get; set; }
}
My problem is how can paint in red only the cells in the datagrid which have errors after the validation process, those errors will be in the ErrorInSheet collection
I don't know If I am making a bad approach because I can't find the way yet, of painting cells indicated in the CErrorExcel class.
I did find the way to do what I asked before, maybe will be usefull to someone some time
I do load the data from Excel with a viewmodel's method and in that process I créate a collection of errors, In the event handler of loading of my scrollviwer I put the call to the process wich paint specifcs cells of my dataGrid and set the tooltip too.
This is the code
private async void ScrollViewer_Loaded(object sender, RoutedEventArgs e)
{
await CargaExcelEnGrid();
}
private async Task CargaExcelEnGrid()
{
try
{
await vm.LoadDatafromExcel(); //loading in the viewmodel
grdExcel.ItemsSource = null;
grdExcel.ItemsSource = vm.TableExcel.DefaultView;
foreach (CErrorExcel error in vm.ErrorExcel)
{
DataGridCell cell = GetCell(error.row, error.col, grdExcel);
cell.Foreground = new SolidColorBrush(Color.FromRgb(255, 0, 0));
cell.ToolTip = error.Error;
}
}
catch ( Exception err)
{
ModernDialog.ShowMessage(err.Message, "Error", MessageBoxButton.OK);
}
}
public DataGridCell GetCell(int rowIndex, int columnIndex, DataGrid dg)
{
DataGridRow row = dg.ItemContainerGenerator.ContainerFromIndex(rowIndex) as DataGridRow;
if (row == null)
{
dg.UpdateLayout();
dg.ScrollIntoView(dg.Items[rowIndex]);
row = (DataGridRow)dg.ItemContainerGenerator.ContainerFromIndex(rowIndex);
}
DataGridCellsPresenter p = GetVisualChild<DataGridCellsPresenter>(row);
DataGridCell cell = p.ItemContainerGenerator.ContainerFromIndex(columnIndex) as DataGridCell;
return cell;
}
Works really good, hope this will help to someone.
bye

Vaadin-Unable to update grid container on combobox value change

I am using vaadin 7.7.7
In a grid i have a combobox as an edited item in one of the columns
as
grid.addColumn("columnProperty").setEditorField(combobox);
I need to update a property/cell in same row based on the combobox selection change
My issue is , the selection change event triggers twice, once when the combobox in clicked and second when the selection value is changed. But the updated value in next cell gets reflected on UI only first time.
Below is the code written . Any solutions?
Combobox.addValueChangeListener(new ValueChangeListener()
#Override
public void valueChange(ValueChangeEvent event) {
// below line works only first time when the combobox is clicked,but i want
//it when the item in the combobox is changed
gridContainer.getContainerProperty(editedRow,"editedColumProperty").setValue("ValueTobeUpdated");}
});
Need to update the unit column on combobox change in edited mode(before saving)
Refer below link for image
example image
You will get value change events even when the field gets value that it should show to the user. In order to get event that indicates that the user has accepted the input you should use field group (setEditorFieldGroup).
From Book of Vaadin example for grid editing:
grid.getColumn("name").setEditorField(nameEditor);
FieldGroup fieldGroup = new FieldGroup();
grid.setEditorFieldGroup(fieldGroup);
fieldGroup.addCommitHandler(new CommitHandler() {
private static final long serialVersionUID = -8378742499490422335L;
#Override
public void preCommit(CommitEvent commitEvent)
throws CommitException {
}
#Override
public void postCommit(CommitEvent commitEvent)
throws CommitException {
Notification.show("Saved successfully");
}
});
Edit
I assume that you want to connect Parameter and Unit comboboxes. I would do that with this kind of value change lister
BeanItemContainer container = new BeanItemContainer<>(
Measurement.class,
measurements);
Grid grid = new Grid(container);
grid.setEditorEnabled(true);
ComboBox parameterComboBox = new ComboBox();
ComboBox unitComboBox = new ComboBox();
parameterComboBox.addItems(Parameter.Pressure, Parameter.Temperature, Parameter.Time);
parameterComboBox.addValueChangeListener(v -> setUnits(parameterComboBox, unitComboBox));
grid.getColumn("parameter").setEditorField(parameterComboBox);
grid.getColumn("unit").setEditorField(unitComboBox);
Units could be updated like this. I think you need to preserve current value and set it back if you replace available items in the combobox.
private void setUnits(ComboBox parameterComboBox, ComboBox unitComboBox) {
Object currentValue = unitComboBox.getValue();
List<String> units = unitsForParameter(parameterComboBox.getValue());
unitComboBox.removeAllItems();
unitComboBox.addItems(units);
if (units.contains(currentValue)) {
unitComboBox.setValue(currentValue);
} else {
unitComboBox.setValue(null);
}
}
private List<String> unitsForParameter(Object value) {
if (value == null) {
return Collections.emptyList();
} else if (value == Parameter.Pressure) {
return asList("Pascal", "Bar");
} else if (value == Parameter.Temperature) {
return asList("Celcius", "Kelvin");
} else if (value == Parameter.Time) {
return asList("Second", "Minute");
} else {
throw new IllegalArgumentException("Unhandled value: " + value);
}
}

How do I search the first column in a datagrid on a user keypress

I have a wpf application that has a datagrid with names in the first column and additional info in other columns. The names are in sorted order. If a user presses a key on the keyboard, say p, I would like the datagrid to go to the first row where the name begins with p. If the user then presses e, go to the first row that begins with pe, etc. Is this possible in a datagrid? I haven't been able to find anything or examples on this. Please help.
For that you should add keydown event.
And Step 1 : OnkeyDown event get text of key.
Step 2 : find item as per your condition from list.
Step 3 : Change selected item.
Step 4 : and scroll datagrid to selected item.
Window keydown event work correctly, in my case datagrid event worked when row was selected.
Here is code.
List<Employee> empData = new List<Employee>();
private Task task;
private CancellationToken token;
private CancellationTokenSource tokenSource;
private string searchText = "";
KeyDownEvent :
private void OnKeyDown(object sender, KeyEventArgs e)
{
if (task != null && tokenSource != null)
{
// cancel task
tokenSource.Cancel();
tokenSource = null;
Console.WriteLine("Task cancel");
}
// Set condition for key
string txt = new KeyConverter().ConvertToString(e.Key);
if (txt.ToString().ToList().Any(x => !Char.IsLetterOrDigit(x)))
{
Console.WriteLine("Retrun from.");
return;
}
searchText = searchText + new KeyConverter().ConvertToString(e.Key);
Console.WriteLine("Search text : " + searchText);
var item = empData.FirstOrDefault(x=>x.FirstName.StartsWith(searchText));
if (item != null)
{
myGrid.SelectedItem = item;
myGrid.UpdateLayout();
myGrid.ScrollIntoView(myGrid.SelectedItem);
}
// create task for clean text
Console.WriteLine("Task generate");
tokenSource = new CancellationTokenSource();
token = tokenSource.Token;
task = new Task(()=> CleanSearchText(token), token);
task.Start();
}
Task for clean text after sometime
private void CleanSearchText(CancellationToken token)
{
// Throw if cancellation request
token.ThrowIfCancellationRequested();
// Wait for sometime for next key prss
Thread.Sleep(400);
// Do nothing if cancelation request
if (token.IsCancellationRequested)
{
return;
}
Console.WriteLine("Clean text");
searchText = "";
}
It is possible. A simple example for Datagrid:
http://www.wpf-tutorial.com/datagrid-control/details-row/
Then handle event keydown in Datagrid
<DataGrid Name="dgUsers" AutoGenerateColumns="False" KeyDown="DgUsers_OnKeyDown">
code behind simple:
private void DgUsers_OnKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
foreach (var row in dgUsers.Items)
{
User user = (User) row;
user.Name = e.Key.ToString();
dgUsers.SelectedItem = row;
break;
}
}
This is already built in!
<DataGrid IsTextSearchEnabled="True" ...
Now just let the models "ToString" method return the text you want to search for - done!
See also https://msdn.microsoft.com/en-us/library/system.windows.controls.textsearch.aspx

WPF/MVVM: SelectedIndex Binding Property not updating when Combobox Selection Changed

I've got a very similar question to Jinesh's. I need to get the value of the SelectedIndex (or SelectedItem or SelectedValue) of a combo box in to my ViewModel code (i.e., when a user selects an item in the combo box, I need that index (or item or value) to update a property in the ViewModel code). I've followed the suggestions in Sheridan's answer and Felix C's answer but my property is not getting updated when the selected item changes. I'm trying to get the newly selected index value as part of my "Update" button code.
View:
<ComboBox Name="cboMonth"
ItemsSource="{Binding MonthsList, Mode=OneTime}"
DisplayMemberPath="month"
SelectedIndex="{Binding MonthIndex, Mode=TwoWay}"/>
<Button Name="btnUpdate"
Content="Update"
Command="{Binding processUpdateButton}" />
ViewModel:
public ObservableCollection<Month> MonthsList { get; set; }
private int _monthIndex;
public int MonthIndex
{
get
{
DateTime today = DateTime.Today;
_monthIndex = today.Month - 1;
return _monthIndex;
}
set
{
if (_monthIndex != value)
{
_monthIndex = value;
RaisePropertyChanged("MonthIndex");
}
}
}
public ICommand processUpdateButton
{
get
{
if (_setUpdateButton == null)
{
_setUpdateButton = new RelayCommand(param => validateOdometer());
}
return _setUpdateButton;
}
}
public void validateOdometer()
{
Console.WriteLine("Validating odometer...");
Console.WriteLine("Month Index: " + (_monthIndex));
}
When my page first renders, I have the combo box defaulting to index 5 (06-June) and the property in question, _monthIndex, reflects 5. When I select a new month in the combo box (e.g., October) then click my update button (btnUpdate), _monthIndex should reflect 9 but it still reflects 5. Why? Appreciate any/all help. Thanks.
The property getter ignores the previously set value and always returns the index of the current month.
The declaration should look like this:
private int monthIndex = DateTime.Today.Month - 1;
public int MonthIndex
{
get { return monthIndex; }
set
{
if (monthIndex != value)
{
monthIndex = value;
RaisePropertyChanged("MonthIndex");
}
}
}

SelectedItem in gridview combo box

I have populated combobox from database in my RadGridView and I want that when it is in add mode my combobox shows its first item as default value. I used following code but I have Error in debuging on commented line in code
private void radGridView_CellValueChanged(object sender, Telerik.WinControls.UI.GridViewCellEventArgs e)
{
if (e.Column.Name == "Productcolumn")
{
//ERROR on debuging following line
RadDropDownListEditor ed = this.radGridView.Columns["UnitPrice"] as RadDropDownListEditor;
if (ed != null)
{
// the default selected Price that will be shown will be the first price, if no price is selected for the current cell
RadDropDownListEditorElement editorElement = (RadDropDownListEditorElement)ed.EditorElement;
editorElement.SelectedIndex = 0;
}
}
}

Resources