Hi! Our colleague Eugene writes periodically in your forum. We use RadTreeListView in our project. As datasource for RadTreeListView we use an ObservableCollection containing hierarchical data. This hierarchical data are displayed in RadTreeListView perfectly well. Please see "Picture.PNG" file attached. But we can't edit information in any cell in second column. When the user does doubleclick on a cell and this cell is switched in edit mode then the data in the cell disappears and the user can't print the new data there. Please see the cell image in edit mode in "Picture2.PNG" file attached. Below is XAML concerning RadTreeListView in our application:
<
telerik:RadTreeListView
Grid.Row
=
"2"
Grid.Column
=
"0"
AutoGenerateColumns
=
"False"
AutoExpandItems
=
"True"
IsSynchronizedWithCurrentItem
=
"True"
ItemsSource
=
"{Binding ProfileTreeRoot.ChildProfileElenents}"
>
<
telerik:RadTreeListView.ChildTableDefinitions
>
<
telerik:TreeListViewTableDefinition
ItemsSource
=
"{Binding ChildProfileElenents}"
/>
</
telerik:RadTreeListView.ChildTableDefinitions
>
<
telerik:RadTreeListView.Columns
>
<
telerik:GridViewDataColumn
IsReadOnly
=
"True"
DataMemberBinding
=
"{Binding Name}"
Header
=
"Наименование"
>
<
telerik:GridViewDataColumn.CellStyle
>
<
Style
TargetType
=
"{x:Type telerik:GridViewCell}"
>
<
Setter
Property
=
"FontWeight"
Value
=
"SemiBold"
/>
</
Style
>
</
telerik:GridViewDataColumn.CellStyle
>
</
telerik:GridViewDataColumn
>
<
telerik:GridViewDataColumn
DataMemberBinding
=
"{Binding CurrentValue}"
Header
=
"Текущее значение"
/>
</
telerik:RadTreeListView.Columns
>
</
telerik:RadTreeListView
>
Where 'ProfileTreeRoot.ChildProfileElements' is ObservableCollection instance. 'ProfileTreeRoot' itself is the instance of Group class where ObservableCollection is. Below is Group class definition. You can see 'ChildProfileElements' ObservableCollection definition there.
public class Group : ProfileElementType
{
#region Fields
private string name;
private string description;
private ObservableCollection<
ProfileElementType
> _childProfileElenents;
private Group parent;
#endregion
#region Constructors
public Group()
{
this.ElementType = this.GetType();
this.ElementTypeName = this.ElementType.Name;
this.Name = "Group 1";
this.ChildProfileElenents = new ObservableCollection<
ProfileElementType
>();
}
#endregion
#region Properties
[Display(Description = "The Name of this Group.", Name = "The Name")]
public string Name
{
get { return this.name; }
set { this.SetProperty(ref this.name, value); }
}
[Display(Description = "The Brief Description of this Group", Name = "The Description")]
public string Description
{
get { return this.description; }
set { this.SetProperty(ref this.description, value); }
}
/// <
summary
>
/// The collection of elements which are the children elements of this group.
/// These elements can be of Group class instances or Register class instances
/// </
summary
>
[Browsable(false)]
public ObservableCollection<
ProfileElementType
> ChildProfileElenents
{
get { return this._childProfileElenents; }
set { this.childProfileElenents = value; }
}
/// <
summary
>
/// Parent group whose ChildProfileElenents collection comprises this Group instance.
/// </
summary
>
[Browsable(false)]
public Group Parent
{
get { return this.parent; }
set { this.parent = value; }
}
#endregion
}
Group class reprecents group containing some registers and some other groups. As you can see the ObservableCollection in Group is defined as the follow:
private ObservableCollection<
ProfileElementType
> _childProfileElenents;
Below the definition of ProfileElementType class and Register class. First 'Register' class is shown:
public class Register : ProfileElementType
{
#region Fields
private int number;
private string name;
private string description;
private string currentValue;
private string defaultValue;
private string minimalValue;
private string maximalValue;
private string dataTypeName;
private RegisterDataAccess accessToData;
private Group parent;
#endregion
#region Constructors
public Register()
{
this.ElementType = this.GetType();
this.ElementTypeName = this.ElementType.Name;
this.Name = "REgister 1";
this.AccessToData = RegisterDataAccess.Read_Write;
}
#endregion
#region Properties
[Display(Description = "Register Address.", Name = "The Address", GroupName = "Common Information")]
public int Number
{
get { return this.number; }
set { this.SetProperty(ref this.number, value); }
}
[Display(Description = "Register Name.", Name = "The Name", GroupName = "Common Information")]
public string Name
{
get { return this.name; }
set { this.SetProperty(ref this.name, value); }
}
[Display(Description = "Breif description.", Name = "The Description", GroupName = "Common Information")]
public string Description
{
get { return this.description; }
set { this.SetProperty(ref this.description, value); }
}
[Display(Description = "Register current value.", Name = "Current Value", GroupName = "Data")]
public string CurrentValue
{
get { return this.currentValue; }
set { this.SetProperty(ref this.currentValue, value); }
}
[Display(Description = "Register default value.", Name = "Default value", GroupName = "Data")]
public string DefaultValue
{
get { return this.defaultValue; }
set { this.SetProperty(ref this.defaultValue, value); }
}
[Display(Description = "Register Minimal Value.", Name = "Minimal Value", GroupName = "Data")]
public string MinimalValue
{
get { return this.minimalValue; }
set { this.SetProperty(ref this.minimalValue, value); }
}
[Display(Description = "Register Maximal Value.", Name = "Maximal Value", GroupName = "Data")]
public string MaximalValue
{
get { return this.maximalValue; }
set { this.SetProperty(ref this.maximalValue, value); }
}
[Display(Description = "Register Data Type.", Name = "Data Type", GroupName = "Data")]
public string DataTypeName
{
get { return this.dataTypeName; }
set { this.SetProperty(ref this.dataTypeName, value); }
}
[Display(Description = "Access to Register Data.", Name = "Data Access", GroupName = "Data")]
public RegisterDataAccess AccessToData
{
get { return this.accessToData; }
set { this.SetProperty(ref this.accessToData, value); }
}
/// <
summary
>
/// Parent group whose ChildProfileElenents collection comprises this Register instance.
/// </
summary
>
[Browsable(false)]
public Group Parent
{
get { return this.parent; }
set { this.parent = value; }
}
#endregion
}
And here is ProfileElementType class definition:
public class ProfileElementType : BindableBase, IProfileElementType
{
#region Fields
private string _elementTypeName;
#endregion
#region Properties
[Browsable(false)]
public string ElementTypeName
{
get { return this._elementTypeName; }
set { this._elementTypeName = value; }
}
#endregion
#region IProfileElementType Implementation
private Type _elementType;
[Browsable(false)]
public Type ElementType
{
get { return this._elementType; }
set { this._elementType = value; }
}
#endregion
}
Can we (in our case) edit cells in RadTreeListViev? After all, if their content is displayed perfectly, then why can not edit it? We really need to get a cell in RadTreeListViev edited. Please help us.
24 Answers, 1 is accepted
I tried to reproduce the issue you've described with the code you've provided, but was, unfortunately, unable to do so. I'm attaching a sample project for reference. Could you please have a look at it and let me know if it differs from the setup you have at your end in any way?
I will be awaiting your response.
Regards,
Dilyan Traykov
Telerik by Progress
Hi, Dilyan. Thank you very much for your support. The architecture of our project is really a bit different. 1) You create an ObservableCollection of Group instances:
this.groups = new ObservableCollection<
Group
>();
2) You create two instances of Group: group (the root group) and childGroup (child group), populate the childGroup with Register instance and populate group.ChildProfileElenents (chield elements collection of group) with childGroup.
// Create root group.
var group = new Group() { Name = "Parent Group" };
// Create child group.
var childGroup = new Group() { Name = "Child Group" };
// Populate child group's child elements collection with one register.
childGroup.ChildProfileElenents.Add(new Register()
{
Name = "Some Name",
CurrentValue = "5"
});
// Populate root group's collection of child elements with childGroup.
group.ChildProfileElenents.Add(childGroup);
3) You populate 'groups' ObservableColection with root group:
this.groups.Add(group);
And after all you have 'Groups' property created on the base of 'groups' ObservableCollection and you use this property as binding source for RadTreeListView. Instead, we create 'group' Group instance as a field, then we create 'Group'
As for us, we do as follows (in terms of the structure of your application):
// Root group.
private
Group _profileTreeRoot;
// Gets or sets the root group.
public
Group ProfileTreeRoot
{
get
{
return
this
._profileTreeRoot; }
// We use SetProperty function here due to using Prism.
set
{
this
.SetProperty(
ref
this
._profileTreeRoot, value); }
}
// Constructor.
public
MyViewModel()
{
this
.ProfileTreeRoot =
new
Group() { Name =
"Parent Group"
};
var childGroup =
new
Group() { Name =
"Child Group"
};
childGroup.ChildProfileElenents.Add(
new
Register()
{
Name =
"Some Name"
,
CurrentValue =
"5"
});
group.ChildProfileElenents.Add(childGroup);
}
and we use ProfileTreeRoot property as data source for binding to view. See below:
<
telerik:RadTreeListView
x:Name
=
"Hierarchical"
Grid.Row
=
"2"
Grid.Column
=
"0"
AutoGenerateColumns
=
"False"
AutoExpandItems
=
"True"
IsSynchronizedWithCurrentItem
=
"True"
ItemsSource
=
"{Binding ProfileTreeRoot.ChildProfileElenents}"
Visibility
=
"{Binding AreRegistersInHierarchyVisible}"
>
<
telerik:RadTreeListView.ChildTableDefinitions
>
<
telerik:TreeListViewTableDefinition
ItemsSource
=
"{Binding ChildProfileElenents}"
/>
</
telerik:RadTreeListView.ChildTableDefinitions
>
<
telerik:RadTreeListView.Columns
>
<
telerik:GridViewDataColumn
IsReadOnly
=
"True"
DataMemberBinding
=
"{Binding Name}"
Header
=
"Наименование"
>
<
telerik:GridViewDataColumn.CellStyle
>
<
Style
TargetType
=
"{x:Type telerik:GridViewCell}"
>
<
Setter
Property
=
"FontWeight"
Value
=
"SemiBold"
/>
</
Style
>
</
telerik:GridViewDataColumn.CellStyle
>
</
telerik:GridViewDataColumn
>
<
telerik:GridViewDataColumn
DataMemberBinding
=
"{Binding CurrentValue}"
Header
=
"Текущее значение"
/>
</
telerik:RadTreeListView.Columns
>
</
telerik:RadTreeListView
>
That is, the binding source for the RadTreeListView is ProfileTreeRoot.ChildProfileElenents ObservableCollection that is colection of ProfileElementType instances. It is defined in Group class as:
private ObservableCollection<
ProfileElementType
> _childProfileElenents;
public ObservableCollection<
ProfileElementType
> ChildProfileElenents
{
get { return this._childProfileElenents; }
set { this._childProfileElenents = value; }
}
Hello, Dilyan. We want to add a little more. You create and populate your data source colection in you ViewModel class cunstructor.
public
MyViewModel()
{
this
.groups =
new
ObservableCollection<Group>();
var group =
new
Group() { Name =
"Parent Group"
};
var childGroup =
new
Group() { Name =
"Child Group"
};
childGroup.ChildProfileElenents.Add(
new
Register()
{
Name =
"Some Name"
,
CurrentValue =
"5"
});
group.ChildProfileElenents.Add(childGroup);
this
.groups.Add(group);
}
But we are doing this in IConfirmNavigationRequest.INavigationAware.OnNavigatedTo event handler (we use Prism). Could this last (that we create and populate our data source colection in this event handler) be the reason of that RadTreeListView does not allow to edit itself normally? Please reply.
Exactly in exactly reproduce code from your example in the constructor of our ViewModel. The result is negative - the list does not allow to edit itself. Could it be due to the fact that in our application the ViewModel and the View are not in the Shell project
but in a separate PrismModule. (Shell project and the PrismModule project are in the same solution.) By pressing the navigation button defined in this PrismModule the call of IRegionManager.ReguestNavigate method is done.
This call put the View in the corresponding region of Shell window. Shell window is in Shell project. Our Prism application is modular. You can see the structure of our application in SolutionStructure.PNG file attached. Where DeviceParameters is PrismModule under review, DeviceParametersViewModel is the ViewModel in this module, DeviceParametersView is the View in this module. DeviceParametersNavigationItemViewModel.cs and DeviceParametersNavigationItemView.xaml are the ViewModel and the View of navigation button that is in this module. When user clicks the navigation button the next command method is caled:
// Navigation command bind to the navigation button's Command property.
public
DelegateCommand<
object
> NavigateToDeviceParametersCommand {
get
;
private
set
; }
// Navigation command's method.
private
void
navigateToDeviceParameters(
object
arg)
{
// Execute navigation.
this
._regionManager.RequestNavigate(ShellRegionsNames.MainContentRegion, _deviceParametersViewUri);
// Check navigation command status.
this
.NavigateToDeviceParametersCommand.RaiseCanExecuteChanged();
}
And as a result DeviceParametersView view is displayed in Shell's MainContentRegion. Shell is in FlowmeterConfigurator project in the solution. Where ShellViewModel.cs is the ViewModel of Shell and Shell.xaml is the View of Shell. You can see it in SolutionStructure.PNG file. Shell.xaml is displayed below.
<!--Shell-->
<
telerik:RadWindow
x:Class
=
"FlowmeterConfigurator.Views.Shell"
xmlns:telerik
=
"http://schemas.telerik.com/2008/xaml/presentation"
xmlns:prism
=
"http://prismlibrary.com/"
xmlns:views
=
"clr-namespace:FlowmeterConfigurator.Views"
prism:ViewModelLocator.AutoWireViewModel
=
"True"
Header
=
"{Binding Title}"
Height
=
"350"
Width
=
"525"
WindowState
=
"Maximized"
>
<!--Controls of modal dialogs output-->
<
i:Interaction.Triggers
>
<!--Custom dialog for user's login-->
<
prism:InteractionRequestTrigger
SourceObject
=
"{Binding LoginConfirmationRequest, Mode=OneWay}"
>
<
prism:PopupWindowAction
IsModal
=
"True"
CenterOverAssociatedObject
=
"True"
>
<
prism:PopupWindowAction.WindowContent
>
<
views:LoginView
/>
</
prism:PopupWindowAction.WindowContent
>
</
prism:PopupWindowAction
>
</
prism:InteractionRequestTrigger
>
<!--Dialog with OK button-->
<
prism:InteractionRequestTrigger
SourceObject
=
"{Binding NotificationRequest, Mode=OneWay}"
>
<
prism:PopupWindowAction
IsModal
=
"True"
CenterOverAssociatedObject
=
"True"
/>
</
prism:InteractionRequestTrigger
>
</
i:Interaction.Triggers
>
<!--Shell's grid-->
<
Grid
>
<
Grid.ColumnDefinitions
>
<
ColumnDefinition
Width
=
"Auto"
/>
<
ColumnDefinition
/>
</
Grid.ColumnDefinitions
>
<
Grid.RowDefinitions
>
<
RowDefinition
Height
=
"Auto"
/>
<
RowDefinition
Height
=
"Auto"
/>
<
RowDefinition
Height
=
"*"
/>
<
RowDefinition
Height
=
"Auto"
/>
</
Grid.RowDefinitions
>
<!--Application's main menue-->
<
StackPanel
Grid.Row
=
"0"
Grid.Column
=
"0"
Grid.ColumnSpan
=
"2"
>
<
telerik:RadMenu
HorizontalAlignment
=
"Stretch"
VerticalAlignment
=
"Top"
AutomationProperties.AutomationId
=
"ApplicationMainMenu"
>
<
telerik:RadMenuItem
Header
=
"Файл"
IsEnabled
=
"{Binding IsFileMenuEnabled}"
>
<
telerik:RadMenuItem
Header
=
"Выход"
Command
=
"{Binding ApplicationShutdownCommand}"
AutomationProperties.AutomationId
=
"ApplicationShutdownMenuItem"
/>
</
telerik:RadMenuItem
>
<
telerik:RadMenuItem
Header
=
"Сервис"
IsEnabled
=
"{Binding IsServiceMenuEnabled}"
>
<
telerik:RadMenuItem
Header
=
"Выполнить авторизацию"
Command
=
"{Binding AuthorizeAgainCommand}"
AutomationProperties.AutomationId
=
"AuthorizeAgainMenuItem"
/>
<
telerik:RadMenuItem
Header
=
"Завершить текщий сеанс"
Command
=
"{Binding TerminateCurrentSessionCommand}"
AutomationProperties.AutomationId
=
"TerminateSessionMenuItem"
/>
</
telerik:RadMenuItem
>
</
telerik:RadMenu
>
</
StackPanel
>
<
Grid
Grid.Row
=
"1"
Grid.Column
=
"0"
>
<
Grid.RowDefinitions
>
<
RowDefinition
/>
</
Grid.RowDefinitions
>
<
Grid.ColumnDefinitions
>
<
ColumnDefinition
Width
=
"Auto"
/>
<
ColumnDefinition
/>
</
Grid.ColumnDefinitions
>
<!--Region for navigation buttons displaying-->
<
StackPanel
Grid.Row
=
"1"
Grid.Column
=
"0"
>
<
ItemsControl
x:Name
=
"NavigationItemsControl"
prism:RegionManager.RegionName
=
"MainNavigationRegion"
>
<
ItemsControl.ItemsPanel
>
<
ItemsPanelTemplate
>
<
UniformGrid
Rows
=
"1"
Width
=
"Auto"
HorizontalAlignment
=
"Left"
/>
</
ItemsPanelTemplate
>
</
ItemsControl.ItemsPanel
>
</
ItemsControl
>
</
StackPanel
>
</
Grid
>
<!--Region for navigated View displaying-->
<
ContentControl
prism:RegionManager.RegionName
=
"MainContentRegion"
Grid.Row
=
"2"
Grid.Column
=
"0"
Grid.ColumnSpan
=
"2"
HorizontalContentAlignment
=
"Stretch"
VerticalContentAlignment
=
"Stretch"
/>
<!--Application's status bar-->
<
StatusBar
Grid.Row
=
"3"
Grid.Column
=
"0"
Grid.ColumnSpan
=
"2"
MinHeight
=
"25"
VerticalAlignment
=
"Bottom"
>
<
StatusBarItem
>
<
TextBlock
Text
=
"{Binding StatusBarText}"
/>
</
StatusBarItem
>
<
StatusBarItem
>
<
telerik:RadProgressBar
Width
=
"300"
Height
=
"20"
Margin
=
"10,0,0,0"
Value
=
"{Binding ProgressBarCurrentValue}"
Visibility
=
"{Binding IsProgresBarVisible}"
Minimum
=
"0"
Maximum
=
"{Binding ProgressBarMaximumValue}"
IsIndeterminate
=
"{Binding IsProgressBarIndeterminated}"
/>
</
StatusBarItem
>
</
StatusBar
>
</
Grid
>
</
telerik:RadWindow
>
Why does RadTreeListView not edit in our application? Рow to get RadTreeListView to let its editing? Please help.
public
class
DeviceParametersViewModel : BindableBase, IConfirmNavigationRequest
{
private
IConnectionService _connectionService;
private
ObservableCollection<ProfileElementType> _deviceProfile;
public
ObservableCollection<ProfileElementType> DeviceProfile
{
get
{
return
this
._deviceProfile; }
set
{
this
.SetProperty(
ref
this
._deviceProfile, value); }
}
. . . . . . .
public
DeviceParametersViewModel(IConnectionService connectionService)
{
. . . . . . .
this
._connectionService = connectionService;
. . . . . . .
}
. . . . . . .
void
INavigationAware.OnNavigatedTo(NavigationContext navigationContext)
{
. . . . . . . . .
this
.DeviceProfile =
new
ObservableCollection<ProfileElementType>(
this
._connectionService.SharedDeviceProfile);
. . . . . . . . .
}
}
I'm afraid that I'm unable the reproduce the issue at my end and without a project to debug, unfortunately, cannot assist you further. May I kindly ask you to open a new support ticket and send over a sample project, isolating the issue, so that I may guide you in finding a solution?
Thank you in advance for your cooperation.
Regards,
Dilyan Traykov
Telerik by Progress
Since you have an active license, you should be able to submit a new support ticket, free of charge. This can be done from the following page.
Regards,
Dilyan Traykov
Telerik by Progress
Regards,
Dilyan Traykov
Telerik by Progress
Navigating to the Get Support page and clicking on the Contact Support Team button at the bottom left corner should lead you to the Available Support List page, provided you're logged in and you have an active subscription. From there, you can open a new support ticket by clicking the Submit support ticket button for the respective product.
Please let me know if you're still unable to successfully open a new ticket, and I will try and assist you further.
Regards,
Dilyan Traykov
Telerik by Progress
As I suggested in my previous reply, it would be most helpful if you could isolate the problem in a sample project, which normally shouldn't be more than 1 megabyte in size. Such a big archive implies a lot of files and folders to navigate through with a lot of dependencies which will be very difficult for me to run and debug.
Please try isolating the issue in a sample project small enough so that you can attach it to your reply. Deleting the bin and obj folders would significally reduce the final size of the file. If you're unable to do so, please open a new support ticket with a link to this thread and we will send over FTP details so that you may send your archive.
Regards,
Dilyan Traykov
Telerik by Progress
I have responded to your support ticket. Thank you for your cooperation.
Regards,
Dilyan Traykov
Telerik by Progress
You can use an FTP client of your choice (FileZilla or SmartFTP for example) to upload the files, using the FTP details I've provided you with.
Regards,
Dilyan Traykov
Telerik by Progress
I have already provided the FTP details in the support ticket you opened. I kindly ask you to continue any further communication on the matter there.
Thank you in advance for your cooperation.
Regards,
Dilyan Traykov
Telerik by Progress