Reputation: 33
I would like to be able to access an item from an ObservableCollection in XAML by using an enum.
I can bind to the ObservableCollection and specify which item in the XAML in the following way:
<Window x:Class="ArrayPropertyBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ArrayPropertyBinding"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MyViewModel />
</Window.DataContext>
<StackPanel>
<CheckBox Content="First" IsChecked="{Binding FilterBy[0],Mode=TwoWay}"/>
<CheckBox Content="Second" IsChecked="{Binding FilterBy[1],Mode=TwoWay}"/>
<CheckBox Content="Thrid" IsChecked="{Binding FilterBy[2],Mode=TwoWay}"/>
<CheckBox Content="Fourth" IsChecked="{Binding FilterBy[3],Mode=TwoWay}"/>
<Button Content="Print" Click="Button_Click_1"/>
<Button Content="SetFourthTrue" Click="Button_Click_SetFourthTrue"/>
</StackPanel>
</Window>
While the view model looks like this
public class MyViewModel
{
public enum Filters
{
First = 0,
Second,
Thrid,
Fourth
}
private ObservableCollection<bool> _filterBy = new ObservableCollection<bool>() { false, false, false, false };
public ObservableCollection<bool> FilterBy
{
get { return _filterBy; }
}
public void PrintFilters()
{
System.Diagnostics.Debug.Write("<<<<");
foreach (bool b in _filterBy)
{
System.Diagnostics.Debug.Write(b);
System.Diagnostics.Debug.Write(" ");
}
System.Diagnostics.Debug.WriteLine(">>>>");
}
public void SetFourthTrue()
{
FilterBy[(int)Filters.Fourth] = true;
}
}
I would like to be able to write the XAML as this:
<CheckBox Content="First" IsChecked="{Binding FilterBy[Filters.First],Mode=TwoWay}"/>
Any pointers or ideas would be greatly appreciated.
Upvotes: 2
Views: 1912
Reputation: 33
So, this is what I have after H.B.'s answer. And it works well for me.
<StackPanel>
<CheckBox Content="First" IsChecked="{Binding Path={local:PathConstructor FilterBy, {x:Static local:Filters.First}}}"/>
<CheckBox Content="Second" IsChecked="{Binding Path={local:PathConstructor FilterBy, {x:Static local:Filters.Second}}}"/>
<CheckBox Content="Thrid" IsChecked="{Binding FilterBy[2],Mode=TwoWay}"/>
<CheckBox Content="Fourth" IsChecked="{Binding FilterBy[3],Mode=TwoWay}"/>
<Button Content="Print" Click="Button_Click_1"/>
<Button Content="SetFourthTrue" Click="Button_Click_SetFourthTrue"/>
</StackPanel>
And in the Code behind
public static class StringEnumConversion
{
public static int ConvertToEnum<T>(object value)
{
Contract.Requires(typeof(T).IsEnum);
Contract.Requires(value != null);
Contract.Requires(Enum.IsDefined(typeof(T), value.ToString()));
return (int)Enum.Parse(typeof(T), value.ToString());
}
}
[ContentProperty("Parameters")]
public class PathConstructor : MarkupExtension
{
public string Path { get; set; }
public IList Parameters { get; set; }
public PathConstructor()
{
Parameters = new List<object>();
}
public PathConstructor(string b, object p0)
{
Path = b;
Parameters = new[] { p0 };
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return new PropertyPath(String.Format("{0}[{1}]",Path,StringEnumConversion.ConvertToEnum<Filters>(Parameters[0])));
}
}
Upvotes: 1
Reputation: 184441
Probably boils down to custom binding path construction, as trying to enter an enum
value directly does not appear to be possible.
Syntax then would be:
{Binding Path={me:PathConstructor FilterBy[(0)], {x:Static myns:Filters.First}}}
(Would recommend moving enums out of classes, otherwise it's myns:MyViewModel+Filters.First
if i am not mistaken)
Upvotes: 3