So in WPF you can use RelativeSource binding and Element binding to bind one visual element’s properties to another visual element’s properties.  You probably have discovered this is non-trivial in Silverlight.  If you are using an MVVM patter to develop your Silverlight application your life just got easier!

Why?  Take this example: 

image

You are building a user editor that lets you link roles to a user.  You want the Add Role and Remove Role buttons to only become enabled if the user has clicked a role. 

The solutions is simple.

In your ViewModel class create a boolean property called AvailableRolesSelectedIndex and a property called IsAddRoleEnabled.

private bool _IsAddRoleEnabled;
public bool IsAddRoleEnabled
{
    get { return _IsAddRoleEnabled; }
    set
    {
        _IsAddRoleEnabled = value;
        SafeNotify("IsAddRoleEnabled");
    }
}
 
private int _AvailableRolesSelectedIndex;
public int AvailableRolesSelectedIndex
{
    get { return _AvailableRolesSelectedIndex; }
    set
    {
        if (value >= 0)
            IsAddRoleEnabled = true;
        else
            IsAddRoleEnabled = false;
 
        _AvailableRolesSelectedIndex = value;
        SafeNotify("AvailableRolesSelectedIndex");
    }
}

(*Note I use a ViewModelBase class that defines a function called SafeNotify().  All this does is fire the PropertyChanged event for the INotifyPropertyChanged implementation on my ViewModel.)

Now, in the XAML, simply bind the AvailableRolesSelectedIndex property to the ListBox's SelectedIndex property and bind the IsEnabled property of the Add Role button to the IsAddRoleEnabled property.

 

<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
    <StackPanel Width="200" Margin="5">
        <TextBlock Text="Available Roles" TextWrapping="Wrap" Margin="5,0,0,0" FontWeight="Bold"/>
        <ListBox Name="lbAvailableRoles" Height="184" ItemsSource="{Binding AllRoles}" SelectedIndex="{Binding AvailableRolesSelectedIndex, Mode=TwoWay}" />
  </StackPanel>
  <StackPanel Margin="5" VerticalAlignment="Center">
      <Button Name="btnAddRole" Content="&gt;&gt; Add Role &gt;&gt;" Margin="0,0,0,14" Click="btnAddRole_Click" IsEnabled="{Binding IsAddRoleEnabled}" />
      <Button Name="btnRemoveRole" Content="&lt;&lt; Remove Role &lt;&lt;" Click="btnRemoveRole_Click" />
  </StackPanel>
  <StackPanel Width="200" Margin="5">
      <TextBlock Text="This User's Roles" TextWrapping="Wrap" Margin="5,0,0,0" FontWeight="Bold"/>
      <ListBox Name="lbAssignedRoles" Height="184" ItemsSource="{Binding User.Roles, Mode=TwoWay}" />
  </StackPanel>
</StackPanel>

I also had to add to the constructor of my ViewModel class an initializer for my AvailableRolesSelectedIndex property.  You want it initialized to –1 or when the initial databinding occurs you will receive an error because the integer’s default value is 0, which does not exist in the listbox until the data is there.

public AdminUsersViewModel()
{
    
    if (UserToEdit == null)
    {
        Title = "ADD USER";
        User = new Employee();
    }
    else
    {
        Title = "EDIT USER";
        User = UserToEdit;
    }
 
    EditImageOpacity            = 0;
    DeleteImageOpacity          = 0;
    AvailableRolesSelectedIndex = -1;
 
    initLists();
}

Now I get a great little effect without having to interact directly with the controls on the View from my ViewModel.

Initial state:

image

Item clicked:

image