WPF - Binding in simple User Control - wpf

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));
}
}

Related

WPF: DependencyProperty.UnsetValue in IMultiValueConverter even though I set the DataContext

I have looked around at the other questions that relate to the DependencyProperty.UnsetValue in IMultiValueConverter, but I havent found an answer that relates to my problem, I think, so here goes:
The problem is Im getting "DependencyProperty.UnsetValue" whatever I try to do with the DataContext.
I have a WPF usercontrol, and in the constructor I create an object, like this:
public partial class Misc_Vehicles_GpsTrackBarContext : UserControl
{
private TimeLine TheTimeLine { get; set; }
public Misc_Vehicles_GpsTrackBarContext()
{
InitializeComponent();
DateTime start = DateTime.Now.AddDays(-1);
TheTimeLine = new TimeLine(start, DateTime.Now);
TheTimeLine.GpsLocations.Add(new GPSLocation(55.13, 13.7, start));
TheTimeLine.GpsLocations.Add(new GPSLocation(55.14, 13.6, start.AddMinutes(3)));
TheTimeLine.GpsLocations.Add(new GPSLocation(55.15, 13.5, start.AddHours(6)));
TheTimeLine.GpsLocations.Add(new GPSLocation(55.16, 13.4, start.AddHours(9)));
TheTimeLine.GpsLocations.Add(new GPSLocation(55.17, 13.3, start.AddHours(12)));
TheTimeLine.GpsLocations.Add(new GPSLocation(55.18, 13.2, start.AddHours(15)));
this.DataContext = this;
}
}
Note: I am now expecting the XAML to be able to access the TheTimeLine (like here http://www.wpf-tutorial.com/data-binding/using-the-datacontext/)
So, the "TheTimeLine" is an object that has some relevant data and the object I want to use when I in the XAML file want to "iterate through" the GPS positions:
class TimeLine
{
public DateTime TimeStart { get; set; }
public DateTime TimeEnd { get; set; }
public TimeSpan Duration
{
get
{
return TimeEnd.Subtract(TimeStart);
}
}
public ObservableCollection<GPSLocation> GpsLocations { get; set; } = new ObservableCollection<GPSLocation>();
public TimeLine(DateTime start, DateTime end)
{
if (start > end)
throw new ArgumentOutOfRangeException("The start parameter cannot be greater than the end parameter");
TimeStart = start;
TimeEnd = end;
}
}
class DriverSession
{
public DateTime TimeStart { get; set; }
public DateTime TimeEnd { get; set; }
public TimeSpan Duration
{
get
{
return TimeEnd.Subtract(TimeStart);
}
}
public DriverSession(DateTime start, DateTime end)
{
if (start > end)
throw new ArgumentOutOfRangeException("The start parameter cannot be greater than the end parameter");
TimeStart = start;
TimeEnd = end;
}
}
And, lastly, the XAML. AS can bee seen, the Binding tags under ItemsControl below use values from both TheTimeLine (TimeStart and TimeEnd) which is the same for each GPSPosition, and then uses the ReceivedTime that is in GPSLocation:
<UserControl
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"
xmlns:local="clr-namespace:tWorks.Alfa.OperatorClient.UserControls.Vehicles"
xmlns:dxlc="http://schemas.devexpress.com/winfx/2008/xaml/layoutcontrol" x:Class="tWorks.Alfa.OperatorClient.UserControls.Vehicles.Misc_Vehicles_GpsTrackBarContext"
mc:Ignorable="d"
d:DesignHeight="260" Width="764.029">
<UserControl.Resources>
<LinearGradientBrush x:Key="HourBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF3EB1EA" Offset="0" />
<GradientStop Color="#FF61BFF1" Offset="0.5" />
<GradientStop Color="#FF01A1F4" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="MinuteBrush" EndPoint="0.999,0.51" StartPoint="0.045,0.51">
<GradientStop Color="#FFEDA25E" Offset="0" />
<GradientStop Color="#FFEDA25E" Offset="0.15" />
<GradientStop Color="#FFFA7A05" Offset="1" />
</LinearGradientBrush>
<local:MarginLengthConverter x:Key="mEventLengthConverter"/>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
</Grid.RowDefinitions>
<Rectangle Fill="AliceBlue"></Rectangle>
<Grid Grid.Row="1">
<Rectangle Margin="0" Height="2" Fill="{DynamicResource HourBrush}"/>
<!-- **** HERE IS THE ItemsControl! **** -->
<ItemsControl x:Name="GpsLocations" ItemsSource="{Binding Path=TheTimeLine.GpsLocations}">
<ItemsPanelTemplate>
<Grid x:Name="EventContainer" Height="20" Background="Gainsboro"/>
</ItemsPanelTemplate>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Canvas>
<!-- **** My rectangles (lines) to draw where I have GPS positions **** -->
<Rectangle StrokeThickness="0" Width="1" Fill="{DynamicResource MinuteBrush}">
<Rectangle.Margin>
<MultiBinding Converter="{StaticResource mEventLengthConverter}">
<Binding Path="TheTimeLine.TimeStart"/> <!-- when DataContext is set to "this", i expected TheTimeLine to be accessible? -->
<Binding Path="TheTimeLine.TimeEnd"/>
<Binding Path="ReceivedTime"/> <!-- ReceivedTime is inside an object called GPSLocation, that I am iterating through -->
<Binding ElementName="EventContainer" Path="ActualWidth"/>
</MultiBinding>
</Rectangle.Margin>
</Rectangle>
</Canvas>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Grid>
And lastly, the annoying error =)
UPDATE
After I updated according to #mm8 comments, I now see this:
So, the values from the "TheTimeLine" fails...
The XAML part regarding the ItemsControl:
<!-- **** HERE IS THE ItemsControl! TheTimeLine.GpsLocations contains GPSLocation objects that has the ReceivedTime used below **** -->
<ItemsControl x:Name="GpsLocations" ItemsSource="{Binding Path=TheTimeLine.GpsLocations}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid x:Name="EventContainer" Height="20" Background="Gainsboro"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Canvas>
<!-- **** My rectangles (lines) to draw where I have GPS positions **** -->
<Rectangle StrokeThickness="0" Width="1" Fill="{DynamicResource MinuteBrush}">
<Rectangle.Margin>
<MultiBinding Converter="{StaticResource mEventLengthConverter}">
<Binding Path="TimeStart" RelativeSource="{RelativeSource AncestorType=UserControl}"/>
<Binding Path="TimeEnd" RelativeSource="{RelativeSource AncestorType=UserControl}"/>
<Binding Path="ReceivedTime"/> <!-- ReceivedTime is inside an object called GPSLocation, ObservableCollection<GPSLocation> -->
<Binding ElementName="EventContainer" Path="ActualWidth"/>
</MultiBinding>
</Rectangle.Margin>
</Rectangle>
</Canvas>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
You can only bind to public properties:
public TimeLine TheTimeLine { get; set; }
Besides, the DataContext of an element in the ItemTemplate is a GPSLocation object assuming you have bound the ItemsSource property to an IEnumerable<GPSLocation>. If you want to bind to the TheTimeLine property of the parent UserControl class, you could use a RelativeSource:
<Binding Path="TheTimeLine.TimeStart" RelativeSource="{RelativeSource AncestorType=UserControl}"/>

Read a custom configuration XAML

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>

Customize Control Template of Silverlight Combobox

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);
}
}

Styling Image Box

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:

Binding values not showing up in ListBox (silverlight 3)

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.

Resources