gpt4 book ai didi

c# - 使用 MVVM 在 Windows 应用商店应用程序中处理事件

转载 作者:行者123 更新时间:2023-11-30 22:10:00 24 4
gpt4 key购买 nike

我正在使用 MVVM 模式(没有框架,只有原始 MVVM)开发 Windows 应用商店应用。

我有一个用户控件 DropboxFileplanUserControl.xaml,它有一个关联的 View 模型 DropboxFileplanViewModel.csDropboxFileplanUserControl 嵌入在 MainPage.xaml 中,MainPage.xaml 具有关联的 View 模型,MainPageViewModel.cs

我的问题是如何在 DropboxFileplanViewModel.cs 中定义和引发事件并在 MainPageViewModel.cs 中处理它?<​​/strong>假设事件要引发的称为 ImageLoaded

编辑:我添加了以下特定代码片段...

DropboxFileplanUserControl.xaml

<UserControl
x:Class="PhotoBox.Controls.DropboxFileplanUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:PhotoBox.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="using:PhotoBox.ViewModels"
xmlns:triggers="using:WinRT.Triggers"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="200">

<UserControl.DataContext>
<viewModels:DropboxFileplanViewModel />
</UserControl.DataContext>

<Grid>
<ListBox>
<!--
...
...
Here I define a ListBox and use interaction triggers to bind the SelectionChanged event to FileplanSelectionChangedCommand on the ViewModel -->
<triggers:Interactions.Triggers>
<triggers:EventTrigger EventName="SelectionChanged">
<triggers:InvokeCommandAction Command="{Binding FileplanSelectionChangedCommand}" PassEventArgsToCommand="True" />
</triggers:EventTrigger>
</triggers:Interactions.Triggers>
</ListBox>
</Grid>

DropboxFileplanViewModel.xaml 注意:我从这个片段中删除了很多代码

public class DropboxFileplanViewModel : ViewModel
{
public DelegateCommand FileplanSelectionChangedCommand { get; set; }

public DropboxFileplanViewModel()
{
FileplanSelectionChangedCommand = new DelegateCommand(FileplanSelectionChanged);
}

private void FileplanSelectionChanged(object parameter)
{
var args = (SelectionChangedEventArgs) parameter;

// Some other stuff is done here but ultimately,
// GetImageFile is called

}

private async void GetImageFile(MetaData file)
{
// Stuff is done here to get the image

// ******************************
// Here I want to raise the event
// ******************************
}
}

DropboxFileplanUserControl 嵌入到 MainPage.xaml 中,如下所示...

MainPage.xaml

<controls:DropboxFileplanUserControl
Grid.Row="0"
DataContext="{Binding FileplanControl}"
Visibility="{Binding IsOpen, Converter={StaticResource BooleanToVisibilityConverter}}"
IsEnabled="{Binding IsOpen}"
<!-- *** Here I need to access the ImageLoaded event and bind it to a command in MainPageViewModel.cs *** -->
/>

因此,总而言之,我需要在 DropboxFileplanViewModel.cs 中声明并引发一个事件,并在 MainPage.xaml 中访问此事件,这样我就可以在 MainPageViewModel.cs。我知道如何将 MainPage.xaml 中的事件绑定(bind)到 MainPageViewModel 中的命令,我只需要知道如何做第一步,即在DropboxFileplanViewModel.cs 并在 MainPage.xaml 中访问它。

最佳答案

在 XAML 中:

<Image Loaded="ImageLoaded" ... />

在 xaml.cs 中:

public MainPageViewModel ViewModel
{
get
{
return this.DataContext as MainPageViewModel;
}
}

public void ImageLoaded( object sender, RoutedEventArgs args )
{
// call down to your view model
if( ViewModel != null )
{
ViewModel.ImageLoadedHandler( );
}
}

针对您的评论,自定义 UserControl 的想法是相同的。我有(我认为是)和有趣的解决方案,我不经常看到其他人实现。每个 ViewModel 都有一个关联的 View (我称之为所有者)和一个逻辑父 View 。类似于允许遍历 UI 元素的可视化树 XAML/WinRT 构造,我们可以在 ViewModel 中创建的父/所有者关系允许在我们的后端代码中进行相同的遍历。请考虑以下事项:

假设我们有一个名为 MyUserControl 的自定义 UserControl,它位于命名空间 MyProject 中。

在 MainPageView.xaml 中:

<Page xmlns:local="MyProject"> // or whatever your fancy-pants namespace scheme is
<Grid>
<local:MyUserControl DataContext="{Binding InnerVM}" />
</Grid>
</Page>

在你的 MainPageView.xaml.cs 中

public MainPageViewModel ViewModel
{
get
{
return this.DataContext as MainPageViewModel;
}
}

public MainPageView()
{
InitializeComponent( );

DataContext = new MainPageViewModel( null, this );
}

我们到了。现在让我们看看 MainPageViewModel.cs

public MainPageViewModel : ViewModelBase // I'll explain ViewModelBase momentarily
{
public MyUserControlViewModel InnerVM { get; set; } // should be a notifying property

public MainPageViewModel( ViewModelBase parent, FrameworkElement owner )
: base( parent, owner )
{
}
}

对于所有意图和目的,MyUserControlViewModel.cs 是相同的。

这是 ViewModelBase.cs(有一些删节):

public ViewModelBase
{
public ViewModelBase Parent { get; set; } // should be a notifying property
public FrameworkElement Owner { get; set; } // should be a notifying property

public ViewModelBase( ViewModelBase parent, FrameworkElement owner )
{
Parent = parent;
Owner = owner;
}
}

简单!正确的?现在,这实际上为我们做了什么?让我们来看看。请考虑以下事项:

在 MyUserControl.xaml 中:

<Image Loaded="ImageLoaded" ... />

在 MyUserControl.xaml.cs 中:

public MyUserControlVieWModel ViewModel
{
get
{
return this.DataContext as MyUserControlVieWModel;
}
}

public void ImageLoaded( object sender, RoutedEventArgs args )
{
// call down to your view model
if( ViewModel != null )
{
ViewModel.ImageLoadedHandler( );
}
}

MyUserControlViewModel.cs

现在您在这里有两个选择(我刚刚意识到我可能为您过度解释了这个问题,我深表歉意。请认真考虑您的问题的选项 1):

1- 使用事件!

public event EventHandler ImageLoaded = delegate { };

public void OnImageLoaded( )
{
ImageLoaded( );
}

然后在MainPageViewModel.cs中

public void OnImageLoaded( )
{
// handle the image loading
}

现在也许把它放在你的构造函数中:

...
InnerVM.ImageLoaded += OnImageLoaded;
...

现在,当从 MyUserControl 中触发事件时,MainPageViewModel 将能够响应。

第二个选项需要更多解释,我现在必须运行。但希望这能让你前进。抱歉,结尾太短了。如果需要,请回答问题。祝你好运!

关于c# - 使用 MVVM 在 Windows 应用商店应用程序中处理事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21123096/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com