2012-02-27 35 views
1

我是MVVM的新手。我有填充Employee列表的列表框。我使用MVVM光Silverlight4列表框對象和按鈕

<ListBox BorderBrush="Transparent" 
     HorizontalContentAlignment="Stretch" 
     VerticalAlignment="Stretch" 
     Name="EmployeeListBox" 
     Background="Transparent" 
     ItemsSource="{Binding Employees}" 
     SelectedItem="{Binding SelectedEmployee, Mode=TwoWay}"> 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
      <Grid Margin="4"> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="200"/> 
        <ColumnDefinition Width="200"/> 
        <ColumnDefinition Width="50"/> 
        <ColumnDefinition Width="50"/> 
        <ColumnDefinition Width="50"/> 
        <ColumnDefinition Width="300"/> 
       </Grid.ColumnDefinitions> 
       <Grid.RowDefinitions> 
        <RowDefinition Height="30"/> 
        <RowDefinition Height="30"/> 
        <RowDefinition Height="30"/> 
        <RowDefinition Height="30"/> 
        <RowDefinition Height="30"/> 
        <RowDefinition Height="Auto"/> 
       </Grid.RowDefinitions> 

       <sdk:Label Grid.Row="0" Grid.Column="0" 
        Content="Name" /> 
       <TextBox Grid.Column="1" Grid.Row="0" 
        Name="EmployeeName" 
        Height="23" 
        Text="{Binding Path=Name, Mode=TwoWay}" 
        VerticalAlignment="Center" 
        HorizontalAlignment="Stretch" /> 
       <Button Grid.Column="2" Grid.Row="0" 
        Name="RefresEmployeeName" 
        Width="20" 
        Height="25" 
        Command="{Binding RefreshEmployeeNameCommand}" 
        Content="Refresh" /> 
       <Button Grid.Column="4" Grid.Row="0" 
        Name="DeleteEmployee" 
        Width="20" 
        Height="25" 
        Content="Delete" 
        Command="{Binding DeleteEmployeeCommand}" /> 
       <sdk:Label Grid.Row="1" Grid.Column="0" 
        Content="Description" /> 
       <TextBox Grid.Column="1" Grid.Row="1" Height="23" 
        Text="Binding Path=Description}" 
        VerticalAlignment="Center" 
        HorizontalAlignment="Stretch" /> 
       <Button Grid.Column="2" Grid.Row="1" 
        Name="RefreshDescription" 
        Width="20" 
        Height="25" 
        Content="Refresh" 
        Command="RefreshDescriptionCommand" /> 
      </Grid> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

這將顯示在員工面前diaplyed與名稱,並在文本框中顯示的描述和接下來的一個刷新按鈕,員工姓名和說明文本框和一個刪除按鈕的員工列表名稱文本框。

在我的ViewModel我已經創建了3 RelayCommands作爲

RelayCommand RefreshEmployeeNameCommand = new RelayCommand(RefreshEmployeeName); 
RelayCommand DeleteEmployeeCommand = new RelayCommand(DeleteEmployee); 
RelayCommand RefreshDescriptionCommand = new RelayCommand(RefreshDescription); 

當我點擊RefreshEmployeeName按鈕,在文本框中的內容應該得到重置爲初始值,如果任何的編輯的員工的名字製成。 當我點擊DeleteEmployee按鈕時,應該刪除SelectedEmployee。 當我點擊RefreshDescription按鈕時,應該重置對描述的任何編輯。

當我點擊RefreshEmployeeName時,RefreshEmployeeName函數沒有在ViewModel中調用。如何捕獲與此按鈕關聯的文本框中的數據。還有如何在單擊按鈕時捕獲選定的項目。當我點擊邊框附近時,選定的項目會更新。

這裏是我的視圖模型:

public IServiceAgent ServiceAgent { get; set; } 

public EditViewModel(IServiceAgent serviceAgent) 
{ 
    if (!IsDesignTime) 
    { 
     if (serviceAgent != null) 
     { 
      ServiceAgent = serviceAgent; 
     } 

     GetEmployees(); 
     WireCommands(); 
    } 
} 

private void WireCommands() 
{ 
    RefreshEmployeeNameCommand = new RelayCommand(RefreshEmployeeName); 
    DeleteEmployeeCommand = new RelayCommand(DeleteEmployee); 
    RefreshEmployeeDescriptionCommand = new RelayCommand(RefreshEmployeeDescription); 
} 

public RelayCommand RefreshEmployeeNameCommand { get; private set; } 

public RelayCommand DeleteEmployeeCommand { get; private set; } 

public RelayCommand RefreshEmployeeDescriptionCommand { get; private set; } 

private void RefreshEmployeeName() 
{ 
    // have to capture the value within the textbox employee name 
} 

private void DeleteEmployee() 
{ 
    // have to capture the employee object which should be deleted 
} 

private void RefreshEmployeeDescription() 
{ 
    // have to capture the value within the textbox employee description 
} 

private ObservableCollection<Employee> _Employees; 
public ObservableCollection<Employee> Employees 
{ 
    get 
    { 
     return _Employees 
    } 
    set 
    { 
     if _Employees!= value) 
     { 
      _Employees= value; 
      OnPropertyChanged("Employees"); 
     } 
    } 
} 

public Employee _SelectedEmployee; 
public DisplayDevice SelectedEmployee 
{ 
    get 
    { 
     return _SelectedEmployee; 
    } 
    set 
    { 
     if (_SelectedEmployee!= value) 
     { 
      _SelectedEmployee= value; 
      OnPropertyChanged("SelectedEmployee"); 
     } 
    } 
} 

private void GetEmployees() 
{ 
    ServiceAgent.GetEmployees((s, e) => Employees = e.Result); 
} 
+1

請發表您的ViewModel。 – cadrell0 2012-02-27 21:38:22

+0

我發佈了我的虛擬機。請讓我知道我錯在哪裏 – 2012-02-27 22:30:44

回答

1

作爲一種預感上怎麼回事錯

的對象內的員工(即每行)必須在他們的按鈕relaycommands的ViewModels。

你可能對你的主視圖模型的relaycommands,但永遠不會被調用,因爲你的列表框的行綁定到員工的項目

+0

你能解釋一下細節嗎?如果你能給我一個很好的例子。 – 2012-02-27 22:30:14

0

一個選擇是對每個Employee對象的RelayCommand ,並綁定到那個。這種方式RelayCommand執行具有所有需要執行的對象上下文。

以下添加到您的Employee對象:

public Employee : ViewModelBase 
{ 
    public RelayCommand RefreshDescriptionCommand {get; private set} 

    // ... 

    public Employee() 
    { 
     RefreshDescriptionCommand = new RefreshDescriptionCommand(RefreshDescription); 

    //... 

    private void RefreshDescription() 
    { 

     //Do whatever 
    } 
} 

你的XAML按鈕需要綁定的命令。由於他們在ItemsTemplate,他們將結合到RefreshDescriptionCommand每個員工個人的對象

<Button ... Command="{Binding RefreshDescriptionCommand}" /> 

當你的命令執行時,它會將該按鈕被放置在該對象的上下文中執行,因此你可以刷新你的描述,更新數據,無論你需要做什麼。

您需要爲每個按鈕重複這些步驟。

需要注意幾個問題:

  1. 確保您的Employee對象實現INotifyPropertyChanged(它如果你使用MVVM光會做,從ViewModelBase繼承)。

  2. 不要把它放在列表框中。對於你想要做的事情,這是一種錯誤的控制。一個ItemsControl更適合這個。 ListBox在這裏唯一真正給你的是能夠選擇一個項目,它看起來不像你需要的。事實上,物品選擇行爲在滾動和按下按鈕時會做出奇怪的事情。

  3. 這可能是在SilverLight中執行此操作的最簡單方法。在WPF中還有其他一些選項,綁定到祖先,但在SilverLight中更難做到。

+0

這是一個錯誤的錯誤,我的代碼中有Command =「{Binding RefreshDescriptionCommand}」。你能否提供一個你的答案選擇的例子,那很好。 – 2012-02-28 14:30:38

+0

此代碼不能正常工作:(請問您可以多描述一下......這是緊急請求 – 2012-02-28 15:11:48

+0

@SnehaSMurthy我修復了按鈕的綁定語句,如果這是在UserControl中,您將擁有將你的x:Type設置爲UserControl,另外,我強烈建議不要在這裏使用ListBox,使用ItemsControl或者ScrollViewer中包含的StackPanel,如果你使用ListBox,你會得到奇怪的行爲 – Robaticus 2012-02-28 15:44:50

0

您的命令沒有被處理,因爲按鈕的數據上下文默認是Employee實體。這是因爲您將ItemsSource設置爲ViewModel上的Employees屬性,則每行都綁定到Employee實體對象。因此,Command綁定正在尋找Employee對象上的Command處理程序,而不是ViewModel。

您需要在命令上設置源以指向您的視圖模型,其中存在命令處理程序。這裏有一個例子:

Command="{Binding Source={StaticResource ViewModel}, Path=RefreshEmployeeNameCommand}" 

視圖模型」是爲視圖創建的EditViewModel實例的名稱。