<telerik:RadTileView Grid.Row="1"> |
<telerik:RadTileViewItem Header="ABC"> |
<telerik:RadFluidContentControl> |
<telerik:RadFluidContentControl.Content> |
<TextBlock Text="Maximize this tile." /> |
</telerik:RadFluidContentControl.Content> |
<telerik:RadFluidContentControl.SmallContent> |
<TextBlock Text="Maximize this tile." /> |
</telerik:RadFluidContentControl.SmallContent> |
<telerik:RadFluidContentControl.LargeContent> |
<Grid> |
<Grid.RowDefinitions> |
<RowDefinition Height="Auto" /> |
<RowDefinition /> |
</Grid.RowDefinitions> |
<Button Height="20" Content="Generate" Click="Button_Click" /> |
<telerik:RadGridView Name="telerikGrid" Grid.Row="1" |
ItemsSource="{Binding Persons, Mode=OneWay}" |
IsReadOnly="True" |
AutoGenerateColumns="False"> |
<telerik:RadGridView.Columns> |
<telerik:GridViewDataColumn DataMemberBinding="{Binding Path=ID, Mode=OneWay}" Header="ID" IsGroupable="False" IsFilterable="False" /> |
<telerik:GridViewDataColumn DataMemberBinding="{Binding Path=Name, Mode=OneWay}" Header="Name" IsGroupable="False" IsFilterable="False" /> |
</telerik:RadGridView.Columns> |
</telerik:RadGridView> |
</Grid> |
</telerik:RadFluidContentControl.LargeContent> |
</telerik:RadFluidContentControl> |
</telerik:RadTileViewItem> |
</telerik:RadTileView> |
public partial class GridControl : UserControl |
{ |
public GridControl() |
{ |
InitializeComponent(); |
this.DataContext = new ViewModel(); |
} |
private void Button_Click(object sender, RoutedEventArgs e) |
{ |
var list = new List<Person>(); |
for (int i = 0; i < 10000; i++) |
{ |
list.Add(new Person(i, "abc")); |
} |
(this.DataContext as ViewModel).Persons = list; |
} |
} |
public class ViewModel : INotifyPropertyChanged |
{ |
private List<Person> _persons = null; |
public List<Person> Persons |
{ |
get { return _persons; } |
set { _persons = value; OnPropertyChanged("Persons"); } |
} |
#region INotifyPropertyChanged Members |
public event PropertyChangedEventHandler PropertyChanged; |
private void OnPropertyChanged(string propertyName) |
{ |
if (PropertyChanged != null) |
PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); |
} |
#endregion |
} |
public class Person |
{ |
private int _id; |
private string _name; |
public Person(int id, string name) |
{ |
_id = id; |
_name = name; |
} |
public int ID |
{ |
get { return _id; } |
} |
public string Name |
{ |
get { return _name; } |
} |
} |
Original post: http://www.telerik.com/community/forums/wpf/chart/radchart-memory-usage-grows-after-regularly-using-radchart-rebind.aspx
Unable to read: I think chrome sent in some odd formatting
I have a solution that consists of a windows form application with an instance of a custom WPF control (within System.Windows.Forms.Integration.ElementHost).
The WPF control contains an instance of the WPF RadChart; its purpose is to host the RadChart and provide helper methods for interpreting a supplied configuration, defining data series, color paletts etc and initialize databinding to a custom data type.
The MVVM technique is used to give each pointmark a particular fill color based on the YValue (implementing INotifyPropertyChanged and so on).
<
ControlTemplate
TargetType
=
"telerikCharting:PointMark"
>
...
Fill="{Binding Path=DataItem.PointMarkColor}"
...
The intent is for uses to run the application normally (interacting with various data-handing forms) and for the application to be deployed on a monitoring workstation, displaying data updates on a flatscreen.
The problem is that there appears to be a memory leak of some kind. I've hunted this down to the point where the new data is updated to the chart.
Firstly, althrough databound, updates to the XValue and YValue of MyData is not made visible to the ViewModel or the Chart via INotifyPropertyChanged. Only a change to 'MyData.ValueStatus' property triggers PropertyChanged (which in turn updates the MyDataViewModel.PointMarkColor).
This was done by design; a specific data result amounts to about 1300 datapoints which are updated at the *same time* and we've found response is faster if we simply update the data soure and rebind the RadChart as opposed to having the chart update each of its 1300 databound points through INotifyPropertyChanged.
I know viewing memory usage within task manager isnt really accurate but the eventual result is clear enough:
The application starts at 110MB and very slowly climbs in resources; a 12-hour run came to 900MB and still climbing.
Running the application (binding the initial data upon load) and omiting any re-binding statement (the in-memory data source is still updated): the application hovers around 100MB to 110=112MB.
Strange thing: minimizing the window drops the usage to 30MB (not actually released, just paged memory i know) but opening the window again from a minimized state puts the Mem usage to about 50MB, and it slowly starts climbing again from there (minimizing and re-opening restarts this process).
I suspect there's not an actual data mem leak as such but there's some form of WPF presenation cache that's being added to when Rebinding to the RadChart; maybe a RePaint/Draw or something.
Is there a way to clear this or avoid it? At this stage, keeping the windows form open (with elementHost containing custom WPF control with RadChart) will eventually consume a monitoring workstation and slowly sip at a user's resources.
Below is a code example from the WPFControl of how i'm initializing and binding data to the chart:
public
void
DefineDataSeries(List<MySeriesConfiguration> series,
bool
zoomEnabled)
{
if
(zoomEnabled)
{
RadChartMain.DefaultView.ChartArea.ZoomScrollSettingsX.ScrollMode = ScrollMode.ScrollAndZoom;
}
else
{
RadChartMain.DefaultView.ChartArea.ZoomScrollSettingsX.ScrollMode = ScrollMode.None;
}
RadChartMain.PaletteBrushes.Clear();
RadChartMain.SeriesMappings.Clear();
for
(
int
i = 0; i < series.Count; i++)
{
//Add color to pallet
RadChartMain.PaletteBrushes.Add(
new
SolidColorBrush(series[i].Definition.TrendSeriesColor));
//Note: HelperClass.GetSeriesMapping uses the i for the seriesMapping.CollectionIndex
SeriesMapping seriesmapping = HelperClass.GetSeriesMapping(series[i], i);
//Create mapping and add to radChart
RadChartMain.SeriesMappings.Add(seriesmapping);
}
RadChartMain.PaletteBrushesRepeat =
true
;
}
//This method gets called from the WinForms application after the data is updated.
public
void
Rebind(ObservableCollection<ObservableCollection<MyDataViewModel>> chartData)
{
RadChartMain.ItemsSource =
this
.ChartData;
RadChartMain.Rebind();
}
When binding and setting Visibility to Collapsed the item's empty space still remains. I have tested with many examples. Simple one is here
<ListBox x:Name="HorizontalListBox"> |
<ListBox.ItemsPanel> |
<ItemsPanelTemplate> |
<telerik:RadCarouselPanel/> |
</ItemsPanelTemplate> |
</ListBox.ItemsPanel> |
<ListBox.ItemTemplate> |
<DataTemplate> |
<TextBlock Text="{Binding Name}" Visibility="{Binding Visible}" /> |
</DataTemplate> |
</ListBox.ItemTemplate> |
</ListBox> |
<Button Height="23" Width="70" Content="lol" Click="Button_Click" /> |
public class Person : INotifyPropertyChanged |
{ |
private int age; |
private String name; |
public Person(String name, int age) |
{ |
this.name = name; |
this.age = age; |
} |
public int Age |
{ |
get { return this.age; } |
set { this.age = value; } |
} |
public String Name |
{ |
get { return this.name; } |
set { this.name = value; } |
} |
Visibility _visible = Visibility.Visible; |
public Visibility Visible |
{ |
get { return _visible; } |
set { _visible = value; OnPropertyChanged("Visible"); } |
} |
#region INotifyPropertyChanged Members |
public event PropertyChangedEventHandler PropertyChanged; |
protected void OnPropertyChanged(string pname) |
{ |
if (PropertyChanged != null) |
PropertyChanged(this, new PropertyChangedEventArgs(pname)); |
} |
#endregion |
} |
HorizontalListBox.ItemsSource = this.CreateItemSource(); // call from anywhere, like constructor |
ObservableCollection<Person> list = new ObservableCollection<Person>(); |
private ObservableCollection<Person> CreateItemSource() |
{ |
list.Add(new Person("George", 15)); |
list.Add(new Person("Rashko", 55)); |
list.Add(new Person("Britney", 60)); |
list.Add(new Person("Joe", 32)); |
list.Add(new Person("Vader", 34)); |
list.Add(new Person("Luke", 16)); |
list.Add(new Person("Jimmy", 105)); |
list.Add(new Person("Batman", 45)); |
list.Add(new Person("Butters", 9)); |
list.Add(new Person("Cartman", 9)); |
list.Add(new Person("Bender", 150)); |
return list; |
} |
private void Button_Click(object sender, RoutedEventArgs e) |
{ |
list[3].Visible = System.Windows.Visibility.Collapsed; |
} |
Now, when you click the button you can see the 4th item got invisible but still taking the space. However if you remove ListBox.ItemsPanel tagand then check again it will be collapsed as it should.
I have checked it with few examples and all are same, is there anyway to do that except removing the item from collection ?
Summary: Setting the 'Maximum' property to a value less than the 'Minimum' property causes any binding on the
'Maximum' property to break.
I have a control that has the following bindings:
<telerik:RadNumericUpDown
Minimum="0"
Maximum="{Binding Path=SnapshotCount, ElementName=GameDisplay, Mode=OneWay, Converter={StaticResource
SnapshotCountToMaxIndexConverter}}"
Value="{Binding Path=SnapshotIndex, ElementName=GameDisplay, Mode=TwoWay}"
/>
The problem is that when the SnapshotCountToMaxIndexConverter converter returns a value less than the minimum (in my particular case it was returning -1) then the following code is triggered to execute in RadRangeBase.cs:
private void CoerceMaximum()
{
if (this.Maximum < this.Minimum)
{
this.SetValue(MaximumProperty, this.Minimum);
}
This appears to break the binding because afterwardsI can see via breakpoints that the
OnMaximumPropertyChanged() method is no longer called.
The net effect of this is that the control becomes unusable because the only value that can then be entered into the field is the minimum value since the minimum and the maximum values are the same and the binding doesn't update what the maximum should be.
Interestly, I also have the exact same binding on a RadSlider() and the binding does not appear to break for that control.
NOTE: This problem is easy to avoid by ensuring that you never specify a maximum value that is less than the minimum.
PS: I love the controls by the way.