开发者

Silverlight MVVM - How Can I Declaratively Bind a ComboBox in a DataGrid CellEditingTemplate using a ViewModel?

I am trying to declaratively bind a ComboBox within a DataGrid CellEditingTemplate using a ViewModel. The ComboBox is not being bound. What am I doing wrong?

XAML:

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"
    xmlns:data="clr-namespace:SilverlightApplication1"
    mc:Ignorable="d"
    x:Class="SilverlightApplication1.EmployeeDetail"
    Width="640" Height="480">

    <UserControl.Resources>
        <data:EmployeeDetailsViewModel
            x:Key="ViewModel"
            d:IsDataSource="True" /开发者_运维百科>
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource ViewModel}}" Background="White">

        <sdk:DataGrid ItemsSource="{Binding Employees,Mode=TwoWay}" AutoGenerateColumns="False" CanUserSortColumns="True" CanUserReorderColumns="True" CanUserResizeColumns="True" GridLinesVisibility="All" Height="317" HorizontalAlignment="Left" Margin="12,136,0,0" Name="EmployeesGrid" VerticalAlignment="Top" Width="605">
            <sdk:DataGrid.Columns>


<!-- snipped from brevity -->

                <sdk:DataGridTemplateColumn Header="Status">
                    <sdk:DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding EmployeeStatus.Description}" TextWrapping="Wrap"></TextBlock>
                        </DataTemplate>
                    </sdk:DataGridTemplateColumn.CellTemplate>
                    <sdk:DataGridTemplateColumn.CellEditingTemplate>
                        <DataTemplate>
                            <ComboBox ItemsSource="{Binding Path=EmployeeStatuses}" SelectedItem="{Binding EmployeeStatus, Mode=TwoWay}" />
                        </DataTemplate>
                    </sdk:DataGridTemplateColumn.CellEditingTemplate>
                </sdk:DataGridTemplateColumn>

            </sdk:DataGrid.Columns>
        </sdk:DataGrid>
        <TextBlock x:Name="SearchLabel" HorizontalAlignment="Left" Margin="12,95,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="106" Height="34"><Run FontWeight="Bold" Text="Search By Name: "/><Run FontSize="9.333" Text="(Last, First)"/></TextBlock>
        <TextBox x:Name="SearchParam" HorizontalAlignment="Left" Margin="144,101,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="162"/>
        <Button x:Name="SearchButton" Content="Search" HorizontalAlignment="Right" Margin="0,102,242,0" VerticalAlignment="Top" Width="75" Click="SearchButton_Click"/>    


    </Grid>
</UserControl>

VIEW MODEL:

using System.Collections.ObjectModel;
using SilverlightApplication1.EmployeeService;
using SilverlightApplication1.ViewModels;

namespace SilverlightApplication1
{
    public class EmployeeDetailsViewModel : ViewModelBase
    {
        readonly IEmployeeServiceAgent _serviceAgent;
        ObservableCollection<EmployeeStatus> _employeeStatuses { get; set; }
        ObservableCollection<Employee> _employees { get; set; }

        public EmployeeDetailsViewModel() : this(new EmployeeServiceAgent()) { }
        public EmployeeDetailsViewModel(IEmployeeServiceAgent serviceAgent)
        {
            if (!IsDesignTime)
            {
                _serviceAgent = serviceAgent;
                GetAllEmployees();
                GetEmployeeStatuses();
            }

        }

        public ObservableCollection<Employee> Employees
        {
            get { return _employees; }
            set
            {
                if(_employees!=value)
                {
                    _employees = value;
                    OnNotifyPropertyChanged("Employees");
                }
            }
        }

        public ObservableCollection<EmployeeStatus> EmployeeStatuses
        {
            get { return _employeeStatuses; }
            set
            {
                if (_employeeStatuses != value)
                {
                    _employeeStatuses = value;
                    OnNotifyPropertyChanged("EmployeeStatuses");
                }
            }
        }

        private void GetAllEmployees()
        {
            _serviceAgent.GetAll((s, e) => Employees = e.Result);
        }

        private void GetEmployeeStatuses()
        {
            _serviceAgent.GetEmployeeStatuses((s, e) => EmployeeStatuses = e.Result);
        }

    }
}

Update:

This seems wrong but I figured out how to get the binding working by re-referencing the ViewModel in the ItemSource Binding:

<ComboBox ItemsSource="{Binding Source={StaticResource ViewModel},Path=EmployeeStatuses}"
                                      DisplayMemberPath="Description"
                                      SelectedItem="{Binding EmployeeStatus, Mode=TwoWay}"  />

However, a am now experiencing a problem where the SelectedItem is not bound! What am I doing wrong?


The problem is a common one that people run into. When you're in the data template of the column, you're no longer bound the the view model. At that point your data context is the EmployeeStatus object (which doesn't have an EmployeeStatuses property to bind to).

So to get the combobox binding to work you can use the ElementName=LayoutRoot to bind back up the tree to the root ViewModel.

Update: Here would be the full syntax for your binding:

{Binding DataContext.EmployeeStatuses, ElementName=LayoutRoot}

Update2: I've actually run into this as well and there is a workaround you have to implement to get the element name binding to work inside a datagrid.


If Bryant's solution does not work (in SL4), use static resources. See this link: http://blog.digitaltools.com/post/2011/05/06/Binding-a-Datagride28099s-ComboBox.aspx

Or, by creating the static resource in xaml: http://forums.silverlight.net/post/370135.aspx

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜