![](/img/trans.png)
[英]MVVM Light - Listbox of UserControls, how to know on which ItemIndex a button is clicked
[英]MVVM Light: How to get data from usercontrols?
我有一個MyDataCollection類,其中包含MyMetaData和MyData。 在我的應用程序中,我有兩個usercontroll,它們向用戶顯示輸入字段。 一個用於MyMetaData,另一個用於MyData。 這兩個用戶控件都包含在MainPage中。
我的問題是:我應該如何從用戶控件中獲取數據,然后用戶輕按保存按鈕(位於主頁上)?
更新我已經將我的代碼相應地更改為blindmeis發布,但是現在未顯示MetaDataView:
<UserControl.Resources>
<DataTemplate x:Key="MetaDataTemplate">
<view:MetaDataView/>
</DataTemplate>
</UserControl.Resources>
<Grid>
<ContentPresenter Content="{Binding MetaDataTemplate}"/>
</Grid>
為什么不以簡單的方式執行mvvm?(首先是viewmodel)。 您說您有一個主頁-這意味着您也有一個mainpageviewmodel。 您的mainpageviewmodel至少處理save命令。 現在,您想在主頁上顯示MyMetaData和MyData。 因此,簡單的方法是在您的mainviewmodel中創建一個MyMetaData實例和一個MyData實例。
public class MainPageViewmodel
{
public ICommand SaveCommand { get; set; }
public MyDataViewmodel MyData { get; set; }
public MyMetaDataViewmodel MyMetaData { get; set; }
public MainPageViewmodel()
{
this.MyData = new MyDataViewmodel();
this.MyMetaData = new MyMetaDataViewmodel();
}
}
public class MyDataViewmodel
{}
public class MyMetaDataViewmodel
{}
您的主頁只需要2個數據模板和2個contentpresenter。
//資源
<DataTemplate DataType="{x:Type Local:MyDataViewmodel}">
<view:MyDataUserControl/>
</DataTemplate>
<DataTemplate DataType="{x:Type Local:MyMetaDataViewmodel}">
<view:MyMetaDataUserControl/>
</DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ContentPresenter Content="{Binding MyData}" Grid.Column="0"/>
<ContentPresenter Content="{Binding MyMetaData}" Grid.Column="1"/>
<Button Content="Save" Command="{Binding SaveCommand}" Grid.Column="2"/>
</Grid>
因為您的mainpageviewmodel具有兩個“子”視圖模型,所以您可以在savecommand上獲得所有想要的信息。
如果您還有其他情況,請更新您的問題,也許發布一些代碼。
編輯:我沒有任何建議,所以只是一個建議:也許瑞秋可以給你一個更好的答案。
<Grid>
<ContentPresenter Content="{Binding MyMetaData}" ContentTemplate="{StaticResource MetaDataTemplate}"/>
</Grid>
如果silverlight無法處理具有數據類型的數據模板,則可以直接將usercontrol放在那里。
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<view:MyDataUserControl DataContext="{Binding MyData}" Grid.Column="0"/>
<view:MyMetaDataUserControl DataContext="{Binding MyMetaData}" Grid.Column="1"/>
<Button Content="Save" Command="{Binding SaveCommand}" Grid.Column="2"/>
</Grid>
由於您將此問題標記為MVVM
,因此ViewModels應該包含SaveCommand
和執行實際保存所需的所有數據
您的MainViewModel
應該包含MyMetaData
和MyData
屬性(它們綁定到各自的UserControls
),並且每個對象都應包含UserControl
所需的任何數據的屬性。 例如,如果您的UserControl
有一個Name
的TextBox
,則您的數據對象應具有TextBox
綁定到的Name
的屬性。
如果“保存”按鈕位於這些UserControls
之一中,則相應的ViewModel應該具有一個“ SaveCommand
,該命令在單擊“ Button
時將被執行。 Save
所需的所有數據也都位於該ViewModel中,因此您可以使用。
如果您的MainViewModel
負責保存數據,那么它應該能夠掛接到子ViewModel的SaveCommand
並附加其自己的方法,例如
this.MyData.SaveCommand = this.SaveCommand();
保存所需的所有數據都可以在this.MyData
找到
如果SaveButton
位於MainView
,而不位於UserControl之一中,則SaveCommand應該是MainViewModel
一部分,並且保存所需的所有數據都可以在this.MyData
或This.MyMetaData
找到。
記住,使用MVVM,您的ViewModels是您的應用程序。 視圖只是一個漂亮的界面,允許用戶與您的ViewModels進行交互。
您應該使用雙向綁定來自動更新控制器中的值。 看一下這篇文章 。
這是一個例子:
<TextBox Text="{Binding MyMetaData, Mode=TwoWay }" />
<TextBox Text="{Binding MyData, Mode=TwoWay }" />
我將為您提供一些示例,說明如何使用MVVM Light Messenger進行ViewModel到ViewModel的通信。 假設您有一個MyDataCollection類:
public class MyDataCollection
{
public int MyData;
public string MyMetaData;
}
在MainViewModel上,您有一個RelayCommand(來自MVVM light工具箱),由View的SaveButton綁定。 執行Connad后,您將必須發送帶有回調操作的消息,以從訂閱者請求數據。 回調將MyDataCollection作為參數:
public class MainViewModel : ViewModelBase
{
public RelayCommand SaveCommand { get; private set; }
//Ctor
public MainViewModel()
{
SaveCommand = new RelayCommand(
() =>
Messenger.Default.Send<NotificationMessageAction<MyDataCollection>>(
new NotificationMessageAction<MyDataCollection>("SaveData", SaveCallback)));
}
private void SaveCallback(MyDataCollection dataCollection)
{
// process your dataCollection...
}
}
UserControlViewModel也具有InputTextBoxes綁定的屬性。 它只需要注冊消息並使用數據屬性調用回調:
public class UserControlViewModel : ViewModelBase
{
//Properties
public string UserControlMetaData { get; set; }
public int UserControlData { get; set; }
//Ctor
public UserControlViewModel()
{
Messenger.Default.Register<NotificationMessageAction<MyDataCollection>>(this, MessageReceived);
}
// private Method to handle all kinds of messages.
private void MessageReceived(MessageBase msg)
{
if(msg is NotificationMessageAction<MyDataCollection>)
{
var actionMsg = msg as NotificationMessageAction<MyDataCollection>;
if(actionMsg.Notification == "SaveData") // Is this the Message, we are looking for?
{
// here the MainViewModels callback is called.
actionMsg.Execute(new MyDataCollection() {MyData = UserControlData, MyMetaData = UserControlMetaData});
}
}
}
}
您將必須使用Messenger或必須在ViewModelLocator上設置屬性
我如何使用它來設置UI語言ViewModel A的Messenger示例,我在這里使用“ SetLanguage”令牌注冊了一個偵聽器:
Messenger.Default.Register<string>(this, "SetLanguage", false, input =>
{
SetLanguage(input);
});
ViewModel B,在這里我發送帶有“ SetLanguage”令牌的消息:
Messenger.Default.Send("en-EN", "SetLanguage");
ViewModel A中的ViewModelLocator示例,我通過定位器訪問ViewModel B中的數據:
short value = 12;
var myFilteredDataList = ViewModelLocator.ViewModelBStatic.MyDataList.Any(m => m.code == value);
我現在有兩種解決方案:
視圖:
<ContentPresenter Content="{Binding MyMetaDataView}" />
ViewModel:
public MetaDataViewModel MyMetaDataViewModel { get; set; }
public MetaDataView MyMetaDataView { get; set; }
public MainViewModel()
{
MyMetaDataViewModel = new MetaDataViewModel();
MyMetaDataView = new MetaDataView();
MyMetaDataView.DataContext = MyMetaDataViewModel;
}
要么 - -
視圖:
<UserControl.Resources>
<DataTemplate x:Key="MetaDataViewTemplate">
<view:MetaDataView />
</DataTemplate>
</UserControl.Resources>
...
<ContentPresenter Content="{Binding MyMetaDataViewModel}" ContentTemplate="{StaticResource MetaDataViewTemplate}"/>
ViewModel:
public MetaDataViewModel MyMetaDataViewModel { get; set; }
public MainViewModel()
{
MyMetaDataViewModel = new MetaDataViewModel();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.