I have read a XAML file using XAMLReader which refer some custom assemblies. Reading a simple XAML file is easy as I can convert the file to stream and then call XAMLReader.Load().During Xaml load code throws exception for the custom assemblies in xmlns .Below is the code added in a WPF application:
public MainWindow()
{
InitializeComponent();
StreamReader streamReader = new StreamReader(Filepath);
string s = streamReader.ReadToEnd();
var index = s.IndexOf("Canvas");
s = s.Insert(index + 6, "xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"");
var c = XamlReader.Parse(s) as Canvas;
}
and my XAML looks like:
<?xml version="1.0" encoding="utf-8"?>
<Canvas xmlns:IN_SE_BlendObjects_FactoryCast_Shapes_BasicShapes="clr-namespace:IN.SE.BlendObjects.FactoryCast.Shapes.BasicShapes;assembly=IN.SE.BlendObjects.FactoryCast" xmlns:IN_SE_BlendObjects_FactoryCast_Shapes_Extended_Shapes="clr-namespace:IN.SE.BlendObjects.FactoryCast.Shapes.Extended_Shapes;assembly=IN.SE.BlendObjects.FactoryCast" xmlns:IN_SE_BlendObjects_FactoryCast_Control_Animation="clr-namespace:IN.SE.BlendObjects.FactoryCast.Control.Animation;assembly=IN.SE.BlendObjects.FactoryCast" Canvas.Left="0" Canvas.Top="0" Margin="0,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Top">
<Canvas.Background>
<SolidColorBrush Color="#FFFFFFFF" />
</Canvas.Background>
<IN_SE_BlendObjects_FactoryCast_Shapes_Extended_Shapes:FCastLinearGauge Canvas.Left="347.632293701172" Canvas.Top="215.769805908203" Width="328.600006103516" Height="131.440002441406" Margin="0,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" LabelText="" LabelFontFamily="Arial" LabelFontSize="12" IsLabelBold="False" IsLabelItalic="False" ShapeCornerStyle="Rounded" IsBackgroundVisible="True" BorderWidth="0" MajorScaleDivision="2" MinorScaleDivision="5" ScaleContainerType="Rectangle" IsLimitScaleVisible="True" ScalePrecision="1" MajorScaleHeight="15" MinorScaleHeight="8" ScaleValueFontFamily="Arial" ScaleValueSize="13" IsScaleValueBold="False" IsScaleValueItalic="False" IsValueVisible="True" ValueFontSize="12" IsValueBold="False" IsValueItalic="False" ValueTextAlignment="Center" Variable="Name:Variable1,Type:,DefaultValue:" MinEUValue="0" MinValue="0" MaxEUValue="100" MaxValue="100" HHLimitValue="80" HLimitValue="60" LLimitValue="40" LLLimitValue="20">
<IN_SE_BlendObjects_FactoryCast_Shapes_Extended_Shapes:FCastLinearGauge.LabelColor>
<SolidColorBrush Color="#FF000000" />
</IN_SE_BlendObjects_FactoryCast_Shapes_Extended_Shapes:FCastLinearGauge.LabelColor>
<IN_SE_BlendObjects_FactoryCast_Shapes_Extended_Shapes:FCastLinearGauge.BackGroundColor>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0" MappingMode="RelativeToBoundingBox" SpreadMethod="Pad" Opacity="1">
<GradientStop Color="#FF095050" Offset="1" />
<GradientStop Color="#FFA2B8BA" Offset="0.354999989271164" />
</LinearGradientBrush>
</IN_SE_BlendObjects_FactoryCast_Shapes_Extended_Shapes:FCastLinearGauge.BackGroundColor>
</IN_SE_BlendObjects_FactoryCast_Shapes_Extended_Shapes:FCastLinearGauge>
</Canvas>
Related
I have two custom controls in wpf. One is Chart control and other is Circular Progress bar. Chart control has following relevant code.
> public int BarValue { get; set; }
> private void DrawData()
> {
> string data = File.ReadAllText(DataSource);
> string[] valueData = data.Split(';');
> string[] strValues = valueData[0].Split(',');
> string[] strYear = valueData[1].Split(',');
> double section = 525 / strValues.Length;
> rectSpace = (section * 20) / 100;
> rectWidth = (section * 80) / 100;
>
>
> for (int i = 0; i < strYear.Length; i++)
> {
>
> Rectangle rec = new Rectangle();
> rec.Width = rectWidth;
> rec.Height = Convert.ToDouble(strValues[i]);
>
> rec.Margin = new Thickness((rectSpace), (350 - rec.Height),
> 0,25);
> rec.Fill = BarsColor;
> panel.Children.Add(rec); rec.MouseDown += Rec_MouseDown; }
private void Rec_MouseDown(object sender,
> MouseButtonEventArgs e)
> {
> BarValue =Convert.ToInt32( ((Rectangle)sender).Height);
> }
Then the ProgressBar has a property Value.
I added both controls to MainWindow. If i click on one rectangle which is an mouseDown event as provided above, how i can change valueproperty of ProgressBar.
I tried
progCircle.Value = chart.BarValue;
in the mainWindow constructor. Not Working.
Any Idea.. Thanks
xml-Main
<Grid Margin="1,0,-318,-30" HorizontalAlignment="Center" Width="1418">
<Rectangle x:Name="MainRec" RadiusX="9" RadiusY="9" Margin="25,38,425,51" Opacity="0.75">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="#FF0F2A3C" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle x:Name="TitleBar" Fill="#FF070E17" HorizontalAlignment="Left" Height="40" Margin="25,38,0,0" RadiusY="9" RadiusX="9" VerticalAlignment="Top" Width="968" Opacity="0.75" MouseDown="TitleBar_MouseDown"/>
<Label Content="Wools Valley" Foreground="Wheat" Margin="43,42,1225,565" Width="150" Height="30" FontSize="14"/>
<Ellipse x:Name="closeButton" HorizontalAlignment="Left" Height="20" Margin="960,52,0,0" VerticalAlignment="Top" Width="20" MouseDown="closeButton_MouseDown" Opacity="0.7" ToolTip="Close" RenderTransformOrigin="4.851,0.607">
<Ellipse.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="DarkCyan" Offset="0"/>
<GradientStop Color="Black" Offset="1"/>
</LinearGradientBrush>
</Ellipse.Fill>
<Ellipse.Triggers>
<EventTrigger RoutedEvent="UIElement.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="closeButton"
Storyboard.TargetProperty="Opacity"
From="0.7" To="1" Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Ellipse.Triggers>
</Ellipse>
<BarGraph2:BarGraph x:Name="bargraph" HorizontalAlignment="Left" Height="425" Margin="79,99,0,0" VerticalAlignment="Top" Width="654" DataSource="D:\\data3.txt" BarsColor="DarkCyan" AxisValueColor="Cyan" titleText="GDP Comparision" />
<ControlExamplesVS:ProgressCircle x:Name="progCircle" HorizontalAlignment="Left" Height="185" Margin="760,99,0,0" VerticalAlignment="Top" Width="184" IndicatorBrush="Cyan" BackgroundBrush="Transparent" ProgressBorderBrush="DarkCyan"/>
</Grid>
If you want to do it in code behind, add this piece of code after you added your controls in the MainWindow:
Binding bind= new Binding();
bind.Source = chart;
bind.Path = new PropertyPath("BarValue");
bind.Mode = BindingMode.TwoWay;
bind.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding(progCircle, CircuòarProgressBar.ValueProperty, bind);
If you have them already in xaml instead you can simply do the following:
<CircularProgressBar Value="{Binding ElementName = chart, Path = Value}"/>
<Chart x:Name = "chart"/>
I want to implement this in Silverlight.
Combobox with an inline filter in the popup
http://gregandora.wordpress.com/2012/01/25/filtering-items-in-a-wpf-combobox/
Unfortunately it's for WPF and XAML is not compatible. It's very hard to convert it or understand how to change the control template of the combobox.
Any idea?
Here's a demo of the solution: https://dl.dropbox.com/u/8424800/StackOverflowSl.html (see ComboBox Filter)
I took the default Silverlight ComboBox template and added a "FilterTextBox" to the Popup section. I couldn't post the whole xaml as it exceeded StackOverflow's limit. The full sources are here as a GitHub Gist. I've left in the important parts. Next, the event handlers on the TextBox needs to be hooked up.
<Style TargetType="ComboBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
<Grid>
<Popup x:Name="Popup">
<Border x:Name="PopupBorder"
Height="Auto"
HorizontalAlignment="Stretch"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="3">
<Border.Background>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Offset="0" Color="#FFFFFFFF" />
<GradientStop Offset="1" Color="#FFFEFEFE" />
</LinearGradientBrush>
</Border.Background>
<Grid>
<TextBox x:Name="FilterTextBox"
Height="22"
VerticalAlignment="Top" />
<ScrollViewer x:Name="ScrollViewer"
Margin="0,25,0,0"
BorderThickness="0"
Padding="1">
<ItemsPresenter />
</ScrollViewer>
</Grid>
</Border>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Wiring up the TextBox
public Q12513294()
{
// Required to initialize variables
InitializeComponent();
InitializeMyCombo(
Enumerable.Range(1, 99).Select(x => "Beer " + x.ToString() + " on the wall"),
(object item, string filter) => (item as String).Contains(filter)
);
}
private void InitializeMyCombo(IEnumerable items, Func<object, string, bool> filter)
{
MyComboBox.Loaded += (s, e) =>
{
// PagedCollectionView implements a filterable collection
PagedCollectionView list = new PagedCollectionView(items);
MyComboBox.ItemsSource = list;
// Set the filter based on the contents of the textbox
TextBox filterTextBox = MyComboBox.GetTemplateChild<TextBox>("FilterTextBox");
list.Filter = new Predicate<object>(
item => filter(item, filterTextBox.Text)
);
// Refresh the filter each time
filterTextBox.TextChanged += (s2, e2) =>
{
list.Refresh();
filterTextBox.Focus();
};
};
}
public static class Helper
{
public static T GetTemplateChild<T>(this DependencyObject parent, string partName)
{
return (T)(VisualTreeHelper.GetChild(parent, 0) as Panel).FindName(partName);
}
}
I want to make a custumized Image Control like MSN with Green light in border
You should use a ContentControl with a custom template. And set the content of the control to the image you want to display.
<ContentControl Template="{DynamicResource TheTemplate}"><Image/></ContentControl>
Then define the style somewhere in your resource dictionary.
<ControlTemplate TargetType="{x:Type ContentControl}">
<Grid>
<!-- Add some fancy borders and colors here -->
<ContentPresenter/>
</Grid>
</ControlTemplate>
I would recommend a UserControl, something like this:
<UserControl x:Class="Test.UserControls.BorderedImageControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Border CornerRadius="{Binding CornerRadius}" Padding="{Binding BorderThickness}" BorderThickness="1">
<Border.BorderBrush>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFE5E5E5" Offset="0"/>
<GradientStop Color="#FF15A315" Offset="1"/>
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="White" Offset="0"/>
<GradientStop Color="#FF67FF68" Offset="1"/>
<GradientStop Color="#FF75E476" Offset="0.496"/>
<GradientStop Color="#FF0FC611" Offset="0.509"/>
</LinearGradientBrush>
</Border.Background>
<Border.Child>
<Image Source="{Binding Source}"/>
</Border.Child>
</Border>
</UserControl>
namespace Test.UserControls
{
public partial class BorderedImageControl : UserControl
{
public static readonly DependencyProperty SourceProperty = Image.SourceProperty.AddOwner(typeof(BorderedImageControl));
public ImageSource Source
{
get { return (ImageSource)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
public static readonly DependencyProperty CornerRadiusProperty = Border.CornerRadiusProperty.AddOwner(typeof(BorderedImageControl));
public CornerRadius CornerRadius
{
get { return (CornerRadius)GetValue(CornerRadiusProperty); }
set { SetValue(CornerRadiusProperty, CornerRadius); }
}
public static readonly DependencyProperty BorderThicknessProperty =
DependencyProperty.Register("BorderThickness", typeof(Thickness), typeof(BorderedImageControl), new UIPropertyMetadata(new Thickness()));
public Thickness BorderThickness
{
get { return (Thickness)GetValue(BorderThicknessProperty); }
set { SetValue(BorderThicknessProperty, value); }
}
public BorderedImageControl()
{
InitializeComponent();
}
}
}
This is comparatively simple, if you want those custom curved shapes you probably need to work with paths instead of a border with corner radius.
Usage example:
<uc:BorderedImageControl Source="http://www.gravatar.com/avatar/c35af79e54306caedad37141f13de30c?s=32&d=identicon&r=PG"
CornerRadius="20" BorderThickness="10" MaxWidth="100" Margin="5"/>
Looks like this:
My problem is certainly right on my face but I can't see it...
I am building a very simple user control - a 3D ellipse - and I expose two properties: LightColor and DarkColor. I need to bind these properties to the gradient in my user control, but it is not showing any color at all. Here's my usercontrol:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TestBrushes"
mc:Ignorable="d"
x:Class="TestBrushes._3DEllipse"
x:Name="UserControl"
d:DesignWidth="200" d:DesignHeight="200">
<Grid x:Name="LayoutRoot">
<Ellipse Name="MainEllipse" Stroke="{x:Null}">
<Ellipse.Fill>
<RadialGradientBrush GradientOrigin="0.5,1.1">
<GradientStop Color="{Binding ElementName=UserControl, Path=LightColor}" Offset="1"/>
<GradientStop Color="{Binding ElementName=UserControl, Path=DarkColor}" Offset="0"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<Ellipse Name="TopReflectionEllipse" Stroke="{x:Null}" Margin="38,0,38,0" VerticalAlignment="Top" Height="90">
<Ellipse.Fill>
<RadialGradientBrush GradientOrigin="0.5,0">
<RadialGradientBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="1" ScaleY="1"/>
<SkewTransform AngleX="0" AngleY="0" CenterX="0.5" CenterY="0.5"/>
<RotateTransform Angle="0" CenterX="0.5" CenterY="0.5"/>
<TranslateTransform X="0" Y="0"/>
</TransformGroup>
</RadialGradientBrush.RelativeTransform>
<GradientStop Color="#A5FFFFFF" Offset="0"/>
<GradientStop Color="#00FFFFFF" Offset="1"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
</Grid>
</UserControl>
and here's my code-behind:
public partial class _3DEllipse
{
public _3DEllipse()
{
InitializeComponent();
}
public Color DarkColor { get; set; }
public Color LightColor { get; set; }
}
If I assign colors as opposed to the binding shown in the code, it works ok, but I want to use the properties I am exposing. What am I doing wrong?
Thanks!
Your issue is likely that you aren't notifiying the UserControl of changes made to the value of the DarkColor and LightColor properties. To do so you'll need to implement the INotifyPropertyChanged interface. The purpose of this interface is to make UI components aware of when the value they're bound to is updated; they subscribe to the PropertyChanged event that is exposed by implementing the interface.
A sample implementation is below, I've left the DarkColor property alone, but it would be updated in the same fashion.
public partial class _3DEllipse : INotifyPropertyChanged
{
private Color _lightColor;
public _3DEllipse()
{
InitializeComponent();
}
// interface implementation
public event PropertyChangedEventHandler PropertyChanged;
public Color DarkColor { get; set; }
public Color LightColor
{
get { return _lightColor; }
set
{
// only update value if its changed
if ( _lightColor == value )
{
return;
}
_lightColor = value;
OnPropertyChanged("LightColor");
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
if ( PropertyChanged == null ) return;
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
I am loading values for a listbox from an xml file. What my problem is i can't get the bindings show the property values of the class that each item is assigned. When i set the Text this way:
<TextBlock Text="{Binding }" Style="{StaticResource TitleBlock}"></TextBlock>
The items show the toString value of the class, but if i use:
<TextBlock Text="{Binding Title}" Style="{StaticResource TitleBlock}"></TextBlock>
I get blank space for each Item in the list box. I hope i have explained my problem well enough. Code posted below:
MapList.xml
<Maps>
<map>
<title>Backlot</title>
<id>mp_backlot</id>
<description>Daytime urban combat.</description>
<thumbnail>mapImages/map11.jpg</thumbnail>
</map>
<map>
<title>Bloc</title>
<id>mp_bloc</id>
<description>Snowy close quarters combat with some sniping available.</description>
<thumbnail>mapImages/map11.jpg</thumbnail>
</map>
<map>
<title>The Bog</title>
<id>mp_bog</id>
<description>Night time map great for any play style.</description>
<thumbnail>mapImages/map11.jpg</thumbnail>
</map>
</Maps>
MainPage.xaml :
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls" x:Class="Cod4ServerTool.MainPage" Height="521" Width="928">
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="0"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.Background>
<ImageBrush Stretch="Uniform" ImageSource="ui_bg.jpg"/>
</Grid.Background>
<controls:TabControl Margin="0,8,0,0" Grid.Row="1">
<controls:TabControl.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="White" Offset="0"/>
<GradientStop Color="#662A2C12" Offset="1"/>
</LinearGradientBrush>
</controls:TabControl.Background>
<controls:TabItem Header="TabItem" Foreground="Black">
<Grid>
<ListBox x:Name="MapsList_lb" Margin="8,8,177,8">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding ThumbNail}" Style="{StaticResource ThumbNailPreview}"></Image>
<TextBlock Text="{Binding Title}" Style="{StaticResource TitleBlock}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#66F0F2F0" Offset="0.254"/>
<GradientStop Color="#CC828C82" Offset="1"/>
<GradientStop Color="#CCD5DED6"/>
</LinearGradientBrush>
</ListBox.Background>
</ListBox>
<ListBox Margin="0,8,8,8" HorizontalAlignment="Right" Width="160">
<ListBox.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#66F0F2F0" Offset="0.254"/>
<GradientStop Color="#CC828C82" Offset="1"/>
<GradientStop Color="#CCD5DED6"/>
</LinearGradientBrush>
</ListBox.Background>
</ListBox>
</Grid>
</controls:TabItem>
<controls:TabItem Header="TabItem">
<Grid/>
</controls:TabItem>
</controls:TabControl>
<Button Height="21" HorizontalAlignment="Right" Margin="0,8,8,0" VerticalAlignment="Top" Width="95" Content="Import Maps" Grid.Row="1" Click="Button_Click"/>
</Grid>
</UserControl>
the .cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Xml.Linq;
namespace Cod4ServerTool
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
DisplayMaps("MapList.xml");
}
private void DisplayMaps(string xmlContent)
{
XDocument xmlMaps = XDocument.Load(xmlContent);
var maps = from map in xmlMaps.Elements("Maps").Elements("map")
select new Map
{
Id = map.Element("id").Value,
Title = map.Element("title").Value,
Description = map.Element("description").Value,
ThumbNail = map.Element("thumbnail").Value,
};
MapsList_lb.SelectedIndex = -1;
MapsList_lb.ItemsSource = maps;
}
}
}
Map.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Cod4ServerTool
{
class Map
{
public string Title { get; set; }
public string Id { get; set; }
public string Description { get; set; }
public string ThumbNail { get; set; }
public override string ToString()
{
return Title;
}
}
}
I would make the maps variable into a List by just adding .ToList();
private void DisplayMaps(string xmlContent)
{
XDocument xmlMaps = XDocument.Load(xmlContent);
var maps = (from map in xmlMaps.Elements("Maps").Elements("map")
select new Map
{
Id = map.Element("id").Value,
Title = map.Element("title").Value,
Description = map.Element("description").Value,
ThumbNail = map.Element("thumbnail").Value,
}).ToList();
MapsList_lb.SelectedIndex = -1;
MapsList_lb.ItemsSource = maps;
}
Edit:
D'oh! and your Map class needs to be declared public. Binding doesn't work with internal types.
The above advice to use ToList still stands, its better for ItemsSource to reference a simple List<Map> than it is to reference a LINQ query that in turns holds on to a tree of XObjects.
Implement interface INotifyPropertyChanged of Map class:
public class Map : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _Title;
public string Title
{
get { return _Title; }
set
{
_Title = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Title"));
}
}
}
...
}
It will work fine after that.
Update:
Make Map class public.