When I create a PointSeries chart, the point's color is determined at moment the chart is showing. But I want the point's color changed with the datasource's some content after the chart was shown.
So I make a new PlotInfo class shown as below, and I set DefaultVisualMaterialSelector bind to PlotInfo's ColorFlag, with a Converter.
Finally, the project doesn't work, the point's color didn't change when I modify the ColorFlag.
So does ChartView3D support this kind of abbility? And how can I get what I want?
public
class
PlotInfo : INotifyPropertyChanged
{
public
event
PropertyChangedEventHandler PropertyChanged;
public
double
XValue {
get
;
set
; }
public
double
YValue {
get
;
set
; }
public
string
ZValue {
get
;
set
; }
private
string
m_sColorFlag;
public
string
ColorFlag
{
get
{
return
m_sColorFlag;}
set
{
m_sColorFlag = value;
if
(
this
.PropertyChanged !=
null
)
{
PropertyChanged.Invoke(
this
,
new
PropertyChangedEventArgs(
"ColorFlag"
));
}
}
}
}
MainWindow.xaml
<
Window
x:Class
=
"VariableMaterial.MainWindow"
xmlns:telerik
=
"http://schemas.telerik.com/2008/xaml/presentation"
xmlns:local
=
"clr-namespace:VariableMaterial"
mc:Ignorable
=
"d"
Title
=
"MainWindow"
Height
=
"350"
Width
=
"525"
>
<
Window.Resources
>
<
local:ColorConvert
x:Key
=
"myColorConvert"
/>
</
Window.Resources
>
<
Grid
>
<
Grid.RowDefinitions
>
<
RowDefinition
Height
=
"30"
/>
<
RowDefinition
/>
</
Grid.RowDefinitions
>
<
ToolBar
Grid.Row
=
"0"
Height
=
"auto"
>
<
Button
Content
=
"SetColorFlag=A"
Click
=
"ButtonA_Click"
Margin
=
"10,0,0,0"
/>
<
Button
Content
=
"SetColorFlag=B"
Click
=
"ButtonB_Click"
Margin
=
"10,0,0,0"
/>
</
ToolBar
>
<
telerik:RadCartesianChart3D
Grid.Row
=
"1"
>
<
telerik:RadCartesianChart3D.XAxis
>
<
telerik:LinearAxis3D
/>
</
telerik:RadCartesianChart3D.XAxis
>
<
telerik:RadCartesianChart3D.YAxis
>
<
telerik:LinearAxis3D
/>
</
telerik:RadCartesianChart3D.YAxis
>
<
telerik:RadCartesianChart3D.ZAxis
>
<
telerik:CategoricalAxis3D
/>
</
telerik:RadCartesianChart3D.ZAxis
>
<
telerik:RadCartesianChart3D.Series
>
<
telerik:PointSeries3D
PointSize
=
"100"
DefaultVisualMaterialSelector
=
"{Binding ColorFlag, Converter={StaticResource myColorConvert}}"
XValueBinding
=
"XValue"
YValueBinding
=
"YValue"
ZValueBinding
=
"ZValue"
ItemsSource
=
"{Binding}"
/>
</
telerik:RadCartesianChart3D.Series
>
<
telerik:RadCartesianChart3D.Grid
>
<
telerik:CartesianChart3DGrid
/>
</
telerik:RadCartesianChart3D.Grid
>
<
telerik:RadCartesianChart3D.Behaviors
>
<
telerik:Chart3DCameraBehavior
/>
</
telerik:RadCartesianChart3D.Behaviors
>
</
telerik:RadCartesianChart3D
>
</
Grid
>
</
Window
>
MainWindow.xaml.cs
using
System;
using
System.Collections.Generic;
using
System.Collections.ObjectModel;
using
System.Globalization;
using
System.Windows;
using
System.Windows.Data;
using
System.Windows.Media;
using
System.Windows.Media.Media3D;
namespace
VariableMaterial
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public
partial
class
MainWindow : Window
{
public
ObservableCollection<PlotInfo> source =
new
ObservableCollection<PlotInfo>();
public
MainWindow()
{
InitializeComponent();
PlotInfo info1 =
new
PlotInfo()
{
XValue = 1,
YValue = 1,
ZValue =
"A"
,
ColorFlag =
"A"
,
};
PlotInfo info2 =
new
PlotInfo()
{
XValue = 2,
YValue = 2,
ZValue =
"B"
,
ColorFlag =
"B"
,
};
source.Add(info1);
source.Add(info2);
this
.DataContext = source;
}
private
void
ButtonA_Click(
object
sender, RoutedEventArgs e)
{
source[0].ColorFlag =
"B"
;
}
private
void
ButtonB_Click(
object
sender, RoutedEventArgs e)
{
source[1].ColorFlag =
"A"
;
}
}
public
class
ColorConvert : IValueConverter
{
private
Dictionary<Color, Material> colorToMaterialDict =
new
Dictionary<Color, Material>();
public
object
Convert(
object
value, Type targetType,
object
parameter, CultureInfo culture)
{
string
colorFlag = (
string
)value;
Color color;
if
(colorFlag ==
"A"
)
{
color = (Color)ColorConverter.ConvertFromString(
"#007ACC"
);
}
else
{
color = (Color)ColorConverter.ConvertFromString(
"#68217A"
);
}
Material material;
if
(!
this
.colorToMaterialDict.TryGetValue(color,
out
material))
{
material =
new
DiffuseMaterial(
new
SolidColorBrush(color));
colorToMaterialDict[color] = material;
}
return
material;
}
public
object
ConvertBack(
object
value, Type targetType,
object
parameter, CultureInfo culture)
{
throw
new
NotImplementedException();
}
}
}
9 Answers, 1 is accepted
Thank you for the provided code snippet.
The reason why the DefaultVisualMaterialSelector is not working is that it expect object of type MaterialSelector. In the convert method the Material object is returned which will not work as expected. In order the approach to work you can again bind the DefaultVisualMaterialSelector property to a ColorFlag, but this time you can declare this property in a ViewModel class. Then you can create custom class which derives from MaterialSelector and perform your custom logic inside the SelectMaterial() method. The final step is to return new instance of this MaterialSelector in the Convert() method of the IValueConverter in order to reset the colors.
I have create a sample project based on the provided code snippet to demonstrate this approach. Hope this information is helpful.
Regards,
Dinko
Progress Telerik
Thanks Dinko !
Your solution is work well.
In your solution, a special property is defined and bind to DefaultVisualMaterialSelector with a converter, so eachtime this property's value was set, the Convert() method was called and a custom MaterialSelector was return. In the custom MaterialSelector class, a override function SelectMaterial() do some bussiness loggic and return material with the specific color.
So I call this special property a RedrawFlag, because eachtime it's value was set, a redraw event on 3Dpoints will trigered. And I also noticed, when I set one 3Dpoint's color, all 3Dpoints in the chart will be redraw. Is that right?
By using your solution, I create a project with a large points chart about 6000, and the point's color is changed as what I want. But when make the program running for about 2 hours (after press RandomColor button), the using memory keep on increasing from 40MB to 200MB, so is there some code wrong?
The code is as following.
Regards,
Star X.
MainWindow.xaml
<
Window
x:Class
=
"Large3DPoint_ColorBind.MainWindow"
xmlns:local
=
"clr-namespace:Large3DPoint_ColorBind"
xmlns:telerik
=
"http://schemas.telerik.com/2008/xaml/presentation"
mc:Ignorable
=
"d"
Title
=
"MainWindow"
Height
=
"600"
Width
=
"1000"
>
<
Window.Resources
>
<
local:MyColorConvert
x:Key
=
"myColorConvert"
/>
</
Window.Resources
>
<
Grid
>
<
Grid.RowDefinitions
>
<
RowDefinition
Height
=
"30"
/>
<
RowDefinition
/>
</
Grid.RowDefinitions
>
<
ToolBar
Grid.Row
=
"0"
Height
=
"auto"
>
<
Button
Content
=
"SetToGreen"
Click
=
"ButtonGreen_Click"
Margin
=
"10,0,10,0"
Background
=
"LightGray"
/>
<
Button
Content
=
"SetToRed"
Click
=
"ButtonRed_Click"
Margin
=
"10,0,10,0"
Background
=
"LightGray"
/>
<
StackPanel
Orientation
=
"Horizontal"
VerticalAlignment
=
"Center"
Margin
=
"40,0,0,0"
Background
=
"GreenYellow"
>
<
TextBlock
x:Name
=
"textBlock"
TextWrapping
=
"NoWrap"
Text
=
"PointIndex(zeroBase):"
Margin
=
"10,0,10,0"
VerticalAlignment
=
"Center"
/>
<
TextBox
x:Name
=
"pointIndex"
Margin
=
"10,0,10,0"
TextWrapping
=
"Wrap"
Text
=
""
Width
=
"50"
Background
=
"AliceBlue"
/>
</
StackPanel
>
<
Button
x:Name
=
"buttonRandom"
Content
=
"RandomColor"
VerticalAlignment
=
"Center"
Width
=
"100"
Background
=
"LightGray"
Click
=
"buttonRandom_Click"
/>
</
ToolBar
>
<
telerik:RadCartesianChart3D
Grid.Row
=
"1"
Background
=
"DimGray"
>
<
telerik:RadCartesianChart3D.XAxis
>
<
telerik:LinearAxis3D
/>
</
telerik:RadCartesianChart3D.XAxis
>
<
telerik:RadCartesianChart3D.YAxis
>
<
telerik:LinearAxis3D
/>
</
telerik:RadCartesianChart3D.YAxis
>
<
telerik:RadCartesianChart3D.ZAxis
>
<
telerik:CategoricalAxis3D
/>
</
telerik:RadCartesianChart3D.ZAxis
>
<
telerik:RadCartesianChart3D.Series
>
<
telerik:PointSeries3D
PointSize
=
"10"
XValueBinding
=
"XValue"
YValueBinding
=
"YValue"
ZValueBinding
=
"ZValue"
ItemsSource
=
"{Binding SourceData}"
DefaultVisualMaterialSelector
=
"{Binding RedrawFlag, Converter={StaticResource myColorConvert}}"
/>
</
telerik:RadCartesianChart3D.Series
>
<
telerik:RadCartesianChart3D.Grid
>
<
telerik:CartesianChart3DGrid
/>
</
telerik:RadCartesianChart3D.Grid
>
<
telerik:RadCartesianChart3D.Behaviors
>
<
telerik:Chart3DCameraBehavior
/>
<
telerik:Chart3DTooltipBehavior
/>
</
telerik:RadCartesianChart3D.Behaviors
>
</
telerik:RadCartesianChart3D
>
</
Grid
>
</
Window
>
MainWindow.xaml.cs
using
System;
using
System.Windows;
namespace
Large3DPoint_ColorBind
{
public
partial
class
MainWindow : Window
{
ViewModel vm;
System.Timers.Timer timer;
Random ra =
new
Random();
public
MainWindow()
{
InitializeComponent();
vm =
new
ViewModel();
this
.DataContext = vm;
}
private
void
ButtonGreen_Click(
object
sender, RoutedEventArgs e)
{
int
iIndex = -1;
if
(
int
.TryParse(pointIndex.Text.ToString(),
out
iIndex) ==
true
)
{
SetPointWithColor(iIndex,
"green"
);
}
}
private
void
ButtonRed_Click(
object
sender, RoutedEventArgs e)
{
int
iIndex = -1;
if
(
int
.TryParse(pointIndex.Text.ToString(),
out
iIndex) ==
true
)
{
SetPointWithColor(iIndex,
"red"
);
}
}
public
void
SetPointWithColor(
int
iIndex,
string
sColor)
{
if
((iIndex >= 0) && (iIndex < vm.SourceData.Count))
{
vm.SourceData[iIndex].ColorFlag = sColor;
//triger the redraw event
vm.RedrawFlag =
""
;
}
else
{
MessageBox.Show(
"Out of range!"
);
}
}
private
void
buttonRandom_Click(
object
sender, RoutedEventArgs e)
{
timer =
new
System.Timers.Timer() { };
timer.Interval = 100;
timer.Elapsed += Timer_Elapsed;
timer.Enabled =
true
;
}
private
void
Timer_Elapsed(
object
sender, System.Timers.ElapsedEventArgs e)
{
//throw new NotImplementedException
int
iColor = ra.Next(0, 100);
string
sColor =
"yellow"
;
if
(iColor%3 == 0)
{
sColor =
"green"
;
}
else
if
(iColor % 3 == 1)
{
sColor =
"red"
;
}
else
{
sColor =
"yellow"
;
}
int
iIndex = ra.Next(0, vm.SourceData.Count);
SetPointWithColor(iIndex, sColor);
}
}
}
PlotInfo.cs
using
Telerik.Windows.Controls;
namespace
Large3DPoint_ColorBind
{
public
class
PlotInfo : ViewModelBase
{
public
double
XValue {
get
;
set
; }
public
double
YValue {
get
;
set
; }
public
double
ZValue {
get
;
set
; }
private
string
m_sColorFlag;
public
string
ColorFlag
{
get
{
return
m_sColorFlag; }
set
{
m_sColorFlag = value;
this
.OnPropertyChanged(
"ColorFlag"
);
}
}
}
}
ViewModel.cs
using
System.Collections.ObjectModel;
using
Telerik.Windows.Controls;
namespace
Large3DPoint_ColorBind
{
public
class
ViewModel : ViewModelBase
{
private
ObservableCollection<PlotInfo> _sourceData;
public
ObservableCollection<PlotInfo> SourceData
{
get
{
return
_sourceData; }
set
{ _sourceData = value;
this
.OnPropertyChanged(
"SourceData"
); }
}
private
string
m_sRedrawFlag;
public
string
RedrawFlag
{
get
{
return
m_sRedrawFlag; }
set
{
m_sRedrawFlag = value;
this
.OnPropertyChanged(
"RedrawFlag"
);
}
}
public
ViewModel()
{
SourceData =
new
ObservableCollection<PlotInfo>();
this
.GetData();
}
private
void
GetData()
{
for
(
int
k = 0; k < 60; k++)
{
for
(
int
m = 0; m < 50; m++)
{
//1st layer
SourceData.Add(
new
PlotInfo { XValue = k, YValue = m, ZValue = 5, ColorFlag =
"white"
});
}
}
for
(
int
k = 0; k < 60; k++)
{
for
(
int
m = 0; m < 50; m++)
{
//2nd layer
SourceData.Add(
new
PlotInfo { XValue = k, YValue = m, ZValue =50, ColorFlag =
"white"
});
}
}
}
}
}
MyDefaultVisualMaterialSelector.cs
using
System;
using
System.Collections.Generic;
using
System.Windows.Media;
using
System.Windows.Media.Media3D;
using
Telerik.Charting;
using
Telerik.Windows.Controls.ChartView;
namespace
Large3DPoint_ColorBind
{
public
class
MyDefaultVisualMaterialSelector : MaterialSelector
{
private
Dictionary<Color, Material> colorToMaterialDict =
new
Dictionary<Color, Material>();
public
override
Material SelectMaterial(
object
context)
{
var value = context
as
XyzDataPoint3D;
var businessItem = value.DataItem
as
PlotInfo;
string
sColorRGB =
"#000000"
;
switch
(businessItem.ColorFlag)
{
case
"yellow"
:
sColorRGB =
"#ffff00"
;
break
;
case
"green"
:
sColorRGB =
"#008000"
;
break
;
case
"red"
:
sColorRGB =
"#ff0000"
;
break
;
case
"white"
:
sColorRGB =
"#FFFFFF"
;
break
;
default
:
break
;
}
Color color = (Color)ColorConverter.ConvertFromString(sColorRGB);
Material material;
if
(!
this
.colorToMaterialDict.TryGetValue(color,
out
material))
{
material =
new
DiffuseMaterial(
new
SolidColorBrush(color));
colorToMaterialDict[color] = material;
}
return
material;
}
}
}
ColorConvert.cs
using
System;
using
System.Collections.Generic;
using
System.Globalization;
using
System.Windows.Data;
namespace
Large3DPoint_ColorBind
{
public
class
MyColorConvert : IValueConverter
{
public
object
Convert(
object
value, Type targetType,
object
parameter, CultureInfo culture)
{
return
new
MyDefaultVisualMaterialSelector();
}
public
object
ConvertBack(
object
value, Type targetType,
object
parameter, CultureInfo culture)
{
throw
new
NotImplementedException();
}
}
}
Thanks Dinko !
Your solution is work well.
In your solution, a special property is defined and bind to DefaultVisualMaterialSelector with a converter, so eachtime this property's value was set, the Convert() method was called and a custom MaterialSelector was return. In the custom MaterialSelector class, a override function SelectMaterial() do some bussiness loggic and return material with the specific color.
So I call this special property a RedrawFlag, because eachtime it's value was set, a redraw event on 3Dpoints will trigered. And I also noticed, when I set one 3Dpoint's color, all 3Dpoints in the chart will be redraw. Is that right?
By using your solution, I create a project with a large points chart about 6000, and the point's color is changed as what I want. But when make the program running for about 2 hours (after press RandomColor button), the using memory keep on increasing from 40MB to 200MB, so is there some code wrong?
The code is as following.
Regards,
Star X.
MainWindow.xaml
<
Window
x:Class
=
"Large3DPoint_ColorBind.MainWindow"
xmlns:local
=
"clr-namespace:Large3DPoint_ColorBind"
xmlns:telerik
=
"http://schemas.telerik.com/2008/xaml/presentation"
mc:Ignorable
=
"d"
Title
=
"MainWindow"
Height
=
"600"
Width
=
"1000"
>
<
Window.Resources
>
<
local:MyColorConvert
x:Key
=
"myColorConvert"
/>
</
Window.Resources
>
<
Grid
>
<
Grid.RowDefinitions
>
<
RowDefinition
Height
=
"30"
/>
<
RowDefinition
/>
</
Grid.RowDefinitions
>
<
ToolBar
Grid.Row
=
"0"
Height
=
"auto"
>
<
Button
Content
=
"SetToGreen"
Click
=
"ButtonGreen_Click"
Margin
=
"10,0,10,0"
Background
=
"LightGray"
/>
<
Button
Content
=
"SetToRed"
Click
=
"ButtonRed_Click"
Margin
=
"10,0,10,0"
Background
=
"LightGray"
/>
<
StackPanel
Orientation
=
"Horizontal"
VerticalAlignment
=
"Center"
Margin
=
"40,0,0,0"
Background
=
"GreenYellow"
>
<
TextBlock
x:Name
=
"textBlock"
TextWrapping
=
"NoWrap"
Text
=
"PointIndex(zeroBase):"
Margin
=
"10,0,10,0"
VerticalAlignment
=
"Center"
/>
<
TextBox
x:Name
=
"pointIndex"
Margin
=
"10,0,10,0"
TextWrapping
=
"Wrap"
Text
=
""
Width
=
"50"
Background
=
"AliceBlue"
/>
</
StackPanel
>
<
Button
x:Name
=
"buttonRandom"
Content
=
"RandomColor"
VerticalAlignment
=
"Center"
Width
=
"100"
Background
=
"LightGray"
Click
=
"buttonRandom_Click"
/>
</
ToolBar
>
<
telerik:RadCartesianChart3D
Grid.Row
=
"1"
Background
=
"DimGray"
>
<
telerik:RadCartesianChart3D.XAxis
>
<
telerik:LinearAxis3D
/>
</
telerik:RadCartesianChart3D.XAxis
>
<
telerik:RadCartesianChart3D.YAxis
>
<
telerik:LinearAxis3D
/>
</
telerik:RadCartesianChart3D.YAxis
>
<
telerik:RadCartesianChart3D.ZAxis
>
<
telerik:CategoricalAxis3D
/>
</
telerik:RadCartesianChart3D.ZAxis
>
<
telerik:RadCartesianChart3D.Series
>
<
telerik:PointSeries3D
PointSize
=
"10"
XValueBinding
=
"XValue"
YValueBinding
=
"YValue"
ZValueBinding
=
"ZValue"
ItemsSource
=
"{Binding SourceData}"
DefaultVisualMaterialSelector
=
"{Binding RedrawFlag, Converter={StaticResource myColorConvert}}"
/>
</
telerik:RadCartesianChart3D.Series
>
<
telerik:RadCartesianChart3D.Grid
>
<
telerik:CartesianChart3DGrid
/>
</
telerik:RadCartesianChart3D.Grid
>
<
telerik:RadCartesianChart3D.Behaviors
>
<
telerik:Chart3DCameraBehavior
/>
<
telerik:Chart3DTooltipBehavior
/>
</
telerik:RadCartesianChart3D.Behaviors
>
</
telerik:RadCartesianChart3D
>
</
Grid
>
</
Window
>
MainWindow.xaml.cs
using
System;
using
System.Windows;
namespace
Large3DPoint_ColorBind
{
public
partial
class
MainWindow : Window
{
ViewModel vm;
System.Timers.Timer timer;
Random ra =
new
Random();
public
MainWindow()
{
InitializeComponent();
vm =
new
ViewModel();
this
.DataContext = vm;
}
private
void
ButtonGreen_Click(
object
sender, RoutedEventArgs e)
{
int
iIndex = -1;
if
(
int
.TryParse(pointIndex.Text.ToString(),
out
iIndex) ==
true
)
{
SetPointWithColor(iIndex,
"green"
);
}
}
private
void
ButtonRed_Click(
object
sender, RoutedEventArgs e)
{
int
iIndex = -1;
if
(
int
.TryParse(pointIndex.Text.ToString(),
out
iIndex) ==
true
)
{
SetPointWithColor(iIndex,
"red"
);
}
}
public
void
SetPointWithColor(
int
iIndex,
string
sColor)
{
if
((iIndex >= 0) && (iIndex < vm.SourceData.Count))
{
vm.SourceData[iIndex].ColorFlag = sColor;
//triger the redraw event
vm.RedrawFlag =
""
;
}
else
{
MessageBox.Show(
"Out of range!"
);
}
}
private
void
buttonRandom_Click(
object
sender, RoutedEventArgs e)
{
timer =
new
System.Timers.Timer() { };
timer.Interval = 100;
timer.Elapsed += Timer_Elapsed;
timer.Enabled =
true
;
}
private
void
Timer_Elapsed(
object
sender, System.Timers.ElapsedEventArgs e)
{
//throw new NotImplementedException
int
iColor = ra.Next(0, 100);
string
sColor =
"yellow"
;
if
(iColor%3 == 0)
{
sColor =
"green"
;
}
else
if
(iColor % 3 == 1)
{
sColor =
"red"
;
}
else
{
sColor =
"yellow"
;
}
int
iIndex = ra.Next(0, vm.SourceData.Count);
SetPointWithColor(iIndex, sColor);
}
}
}
PlotInfo.cs
using
Telerik.Windows.Controls;
namespace
Large3DPoint_ColorBind
{
public
class
PlotInfo : ViewModelBase
{
public
double
XValue {
get
;
set
; }
public
double
YValue {
get
;
set
; }
public
double
ZValue {
get
;
set
; }
private
string
m_sColorFlag;
public
string
ColorFlag
{
get
{
return
m_sColorFlag; }
set
{
m_sColorFlag = value;
this
.OnPropertyChanged(
"ColorFlag"
);
}
}
}
}
ViewModel.cs
using
System.Collections.ObjectModel;
using
Telerik.Windows.Controls;
namespace
Large3DPoint_ColorBind
{
public
class
ViewModel : ViewModelBase
{
private
ObservableCollection<PlotInfo> _sourceData;
public
ObservableCollection<PlotInfo> SourceData
{
get
{
return
_sourceData; }
set
{ _sourceData = value;
this
.OnPropertyChanged(
"SourceData"
); }
}
private
string
m_sRedrawFlag;
public
string
RedrawFlag
{
get
{
return
m_sRedrawFlag; }
set
{
m_sRedrawFlag = value;
this
.OnPropertyChanged(
"RedrawFlag"
);
}
}
public
ViewModel()
{
SourceData =
new
ObservableCollection<PlotInfo>();
this
.GetData();
}
private
void
GetData()
{
for
(
int
k = 0; k < 60; k++)
{
for
(
int
m = 0; m < 50; m++)
{
//1st layer
SourceData.Add(
new
PlotInfo { XValue = k, YValue = m, ZValue = 5, ColorFlag =
"white"
});
}
}
for
(
int
k = 0; k < 60; k++)
{
for
(
int
m = 0; m < 50; m++)
{
//2nd layer
SourceData.Add(
new
PlotInfo { XValue = k, YValue = m, ZValue =50, ColorFlag =
"white"
});
}
}
}
}
}
MyDefaultVisualMaterialSelector.cs
using
System;
using
System.Collections.Generic;
using
System.Windows.Media;
using
System.Windows.Media.Media3D;
using
Telerik.Charting;
using
Telerik.Windows.Controls.ChartView;
namespace
Large3DPoint_ColorBind
{
public
class
MyDefaultVisualMaterialSelector : MaterialSelector
{
private
Dictionary<Color, Material> colorToMaterialDict =
new
Dictionary<Color, Material>();
public
override
Material SelectMaterial(
object
context)
{
var value = context
as
XyzDataPoint3D;
var businessItem = value.DataItem
as
PlotInfo;
string
sColorRGB =
"#000000"
;
switch
(businessItem.ColorFlag)
{
case
"yellow"
:
sColorRGB =
"#ffff00"
;
break
;
case
"green"
:
sColorRGB =
"#008000"
;
break
;
case
"red"
:
sColorRGB =
"#ff0000"
;
break
;
case
"white"
:
sColorRGB =
"#FFFFFF"
;
break
;
default
:
break
;
}
Color color = (Color)ColorConverter.ConvertFromString(sColorRGB);
Material material;
if
(!
this
.colorToMaterialDict.TryGetValue(color,
out
material))
{
material =
new
DiffuseMaterial(
new
SolidColorBrush(color));
colorToMaterialDict[color] = material;
}
return
material;
}
}
}
ColorConvert.cs
using
System;
using
System.Collections.Generic;
using
System.Globalization;
using
System.Windows.Data;
namespace
Large3DPoint_ColorBind
{
public
class
MyColorConvert : IValueConverter
{
public
object
Convert(
object
value, Type targetType,
object
parameter, CultureInfo culture)
{
return
new
MyDefaultVisualMaterialSelector();
}
public
object
ConvertBack(
object
value, Type targetType,
object
parameter, CultureInfo culture)
{
throw
new
NotImplementedException();
}
}
}
oh my god, sorry i don't know why it was paste twice, maybe my network is going wrong.
Can the administrator of the web delete one of them?
Thank you for the provided code snippets.
I am currently investigating your scenario and I need more time. Will contact you tomorrow with further information about your case.
Regards,
Dinko
Progress Telerik
It seems that the material caching mechanism doesn't get cleaned in some case, but we will do some additional time to check why this happens and what alternative solution to suggest.
Regards,
Martin Ivanov
Progress Telerik
Thanks Dinko,
Thanks Martin Ivanov!
Hello Star X,
The memory increases because the material/shape cache of the chart populates with new materials each time a new instance of the custom material selector is created. This way each selector instance creates new instances of the materials. Even though the custom selector caches the materials, this happens only for the objects created in the current instance of the selector. The next time a color changes, a new instance of the selector is created along with the new materials.
To resolve this, use a static field for the "colorToMaterialDict" dictionary in the MyDefaultVisualMaterialSelector class. Here is an example in code:
public class MyDefaultVisualMaterialSelector : MaterialSelector
{
private static Dictionary<Color, Material> colorToMaterialDict = new Dictionary<Color, Material>();
// other code here
}
Regards,
Martin Ivanov
Progress Telerik
Hello Martin Ivanov,
Your solution is very good!
After I apply your solution to my project, the program run with a beginning memory size of 38MB,and grow to a max memory size of 48MB in half hour, and it stabilized to this value during the next 2 hours.
So thanks you all, it help me a lot!
Thanks!
Regards,
Star X