views:

213

answers:

3

I have one main outstanding issue, I know now how to databind to lists and individual items, but there is one more problem I have with this, I need to bind a listbox to some properties that are in a Class.
For Example I have two Properties that are bound in some XAML in a class called Display:

Public Property ShowEventStart() As Visibility
Public Property ShowEventEnd() As Visibility

I can use these in my XAML but I want them to be in a ListBox/Drop-down List, how can I have my properties show in this list and be able to change their values, does it have to be a List to be in a List?
I just want to be able to modify these properties from a Drop-down list to toggle the Visibility of the ShowEventStart and ShowEventEnd Property Values using the Checkboxes in the Drop-down List.

Plus this must be a Silverlight 3.0 solution, I cannot figure out how to have something that can be bound in the XAML which is not a list and then bound it as a list to modify these items!

I just need a list of Checkboxes which alter the values of the Class Properties such as ShowEventStart and ShowEventEnd, there are other properties but this will be a start.

A: 

I tried to mock up something similar. See how this works for you and let me know if I misunderstood the question.

From MainPage.xaml:

<StackPanel Orientation="Horizontal">
        <ListBox SelectedItem="{Binding ShowControls, Mode=TwoWay}" x:Name="VisibilityList"/>
        <Button Content="Test" Visibility="{Binding ShowControls}"/>
        <CheckBox Content="Test 2" Visibility="{Binding ShowControls}"/>
    </StackPanel>

The code behind MainPage.xaml.cs:

public partial class MainPage : UserControl
    {
        VisibilityData visibilityData = new VisibilityData();

        public MainPage()
        {
            InitializeComponent();

            VisibilityList.Items.Add(Visibility.Visible);
            VisibilityList.Items.Add(Visibility.Collapsed);

            this.DataContext = visibilityData;
        }
    }

And the data class:

public class VisibilityData : INotifyPropertyChanged
    {
        private Visibility showControls = Visibility.Visible;

        public Visibility ShowControls
        {
            get { return showControls; }
            set
            {
                showControls = value;
                OnPropertyChanged("ShowControls");
            }
        }

        private void OnPropertyChanged(string p)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(p));
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

When you run that code you should get a ListBox with the options Visible and Collapsed and when you choose an option you should see the visibility of the button and checkbox is changed to reflect your choice. Let me know if that's not what you were looking for.

James Cadd
Thanks for that but I realise I have not worded my question correctly, however this has been a helpful example for usage of the property changed item, which I also needed! I want to have a List of Checkboxes which change Properties in my Class, I could have them in a list but I need them to be Class Properties for Binding in XAML in a non-list UI.
RoguePlanetoid
So if I changed out the ListBox in my example for a CheckBox would that be what you want?
James Cadd
A: 

After thinking about this the solution occured to me, which is to construct the List in XAML then using a Converter on the Checkboxes to convert their Boolean IsChecked to the Property Visibility Property in the Class.
You can create a list such as:

            <ComboBox Canvas.Left="6" Canvas.Top="69" Width="274" Height="25" Name="Display">
                <StackPanel Orientation="Horizontal">
                    <CheckBox IsChecked="{Binding Path=Display.EventStart,Mode=TwoWay,Converter={StaticResource VisibilityConverter}}"/>
                    <TextBlock Text="Event Start"/>
                </StackPanel>
                <StackPanel Orientation="Horizontal">
                    <CheckBox IsChecked="{Binding Path=Display.EventEnd,Mode=TwoWay,Converter={StaticResource VisibilityConverter}}"/>
                    <TextBlock Text="Event End"/>
                </StackPanel>
            </ComboBox>

I can then Bind to the Two Properties I want (this example from the actual application).

RoguePlanetoid
+1  A: 

You can create a PropertyWrapper class and in you window code behind expose a property that returns a List<PropertyWrapper> and bind your ListBox.ItemsSource to it.

public class PropertyWrapper
 {
  private readonly object target;
  private readonly PropertyInfo property;

  public PropertyWrapper(object target, PropertyInfo property)
  {
   this.target = target;
   this.property = property;
  }

  public bool Value
  {
   get
   {
    return (bool) property.GetValue(target, null);
   }
   set
   {
    property.SetValue(target, value, null);
   }
  }

  public PropertyInfo Property
  {
   get
   {
    return this.property;
   }
  }
 }

your window code behind:

public partial class Window1 : Window, INotifyPropertyChanged
 {
public Window1()
  {
   InitializeComponent();

   properties = new List<PropertyWrapper>
                 {
                  new PropertyWrapper(this, typeof(Window1).GetProperty("A")),
        new PropertyWrapper(this, typeof(Window1).GetProperty("B")),
                 };

   this.DataContext = this;
  }

  private List<PropertyWrapper> properties;
  public List<PropertyWrapper> Properties
  {
   get { return properties; }
  }


  private bool a;

  private bool b = true;

  public bool A
  {
   get
   {
    return a;
   }
   set
   {
    if (value != a)
    {
     a = value;
     NotifyPropertyChange("A");
    }
   }
  }

  public bool B
  {
   get
   {
    return b;
   }
   set
   {
    if (value != b)
    {
     b = value;
     NotifyPropertyChange("B");
    }
   }
  }

  protected void NotifyPropertyChange(string propertyName)
  {
   if (PropertyChanged != null)
   {
    PropertyChanged.Invoke(
     this, new PropertyChangedEventArgs(propertyName));
   }
  }

  public event PropertyChangedEventHandler PropertyChanged;
 }

your window markup:

            <ListBox ItemsSource="{Binding Path=Properties}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding Path=Property.Name}"/>
                            <CheckBox IsChecked="{Binding Path=Value}" />
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

Hope this helps

Claudiu
That is an interesting solution, to turn the properties from a Class into a list, I may try it this way, as this is more like the solution I wanted - essentially I am building a list manually and binding to each property per list item, although it works this solution may be more useful as I have many properties to bind to.
RoguePlanetoid
Also if you want to add properties of different types you can replace the CheckBox with a container control and use a dataTemplate that binds by type and add a data template for each type (to edit a boolean value with a check box, a string with a textBox and so on). If you need this let me know and I will write an example for you.
Claudiu