【发布时间】:2020-05-08 17:51:47
【问题描述】:
我有这个带有 2 个按钮的视图(片段)。如果我单击左侧按钮,视图 2 将打开。如果我单击右键,视图 3 将打开。我正在使用 Caliburn Micro。因此,Button 的 x:Name 值是单击按钮后调用的 View Model 方法的名称。
视图1:
<StackPanel Name="PnlButtons"
Grid.Row="1"
Grid.ColumnSpan="2"
HorizontalAlignment="Center"
Orientation="Horizontal"
Opacity="1">
<Button x:Name="ArtikelAuswahl"
Background="Bisque"
Content="Artikel auswählen"
Width="170" Height="25"
FontFamily="Verdana">
</Button>
<Button x:Name="SonderAuswahl"
Background="BlanchedAlmond"
Content="Sonderartikel hinzufügen"
Width="170" Height="25"
FontFamily="Verdana">
</Button>
</StackPanel>
这是在单击按钮后调用的 2 个方法。您可以看到它们具有相同的名称。 现在人们说禁止在视图模型中打开视图。这就是当我想打开一个新视图时,我在我的方法中使用 IWindowManager 实例 winmanager 的原因。我没有创建新的视图实例,而是创建了一个新的视图模型实例! 第一个问题:这是否违反了 MVVM 的规则?
ViewModel1:
public class CreateLieferscheinViewModel : Conductor<object>
{
private IWindowManager winmanager = new WindowManager();
public InventurartikelViewModel inventur = new InventurartikelViewModel();
public SonderartikelViewModel sonder = new SonderartikelViewModel();
public void ArtikelAuswahl()
{
wwinmanager.ShowWindow(inventur, null, null);
}
public void SonderAuswahl()
{
winmanager.ShowWindow(sonder,null,null);
}
/* ToBeImplemented: Invoke this method once `Artikelliste` is filled!!! */
public void ArtikellisteUmformen()
{
for (int k = 0; k < inventur.Artikelliste.Count; k++)
{
Artikelsammlung.Add(new ArtikelModel()); //every selected article will get added to Artikelsammlung
//get each selected article unfiltered (unformatted)
Artikelsammlung[k].Bezeichnung = inventur.Artikelliste[k].ToString();
//Extract the unit out of the Artikel-String
Artikelsammlung[k].Einheit = Zeichenketten.TextFindenVonBisEnde(Artikelsammlung[k].Bezeichnung, "<", ">");
//remove "in <Einheit>" from the Artikel-String
Artikelsammlung[k].Bezeichnung = Zeichenketten.EinheitEntfernen(Artikelsammlung[k].Bezeichnung);
/*
* Bezeichnung and Einheit are now properly formatted...
*/
}
}
}
private ObservableCollection<ArtikelModel> _artikelsammlung;
public ObservableCollection<ArtikelModel> Artikelsammlung
{
get { return _artikelsammlung; }
set
{
_artikelsammlung = value;
OnPropertyChanged("Artikelsammlung");
}
}
好的,现在假设 ArtikelAuswahl 被调用。感谢 Caliburn Micro,View2 显示:
视图2:
<Window x:Class="Lieferscheine.Views.InventurartikelView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Lieferscheine.Views"
xmlns:main="clr-namespace:Lieferscheine"
xmlns:cal="http://www.caliburnproject.org"
mc:Ignorable="d" Title="Inventurartikel suchen"
Height="450" Width="370">
<StackPanel Height="423" VerticalAlignment="Bottom">
<Label Name="lblArtikelbezeichnung" Content="Artikelbezeichnung:" Margin="20, 20, 20, 0"></Label>
<TextBox Name="BezText"
Width="Auto"
Margin="20, 0, 20, 0"
IsEnabled="{Binding Path=BezEnabled}"
cal:Message.Attach="[Event KeyUp] = [Action KeyUpBez($executionContext)]">
</TextBox>
<Label Name="lblLieferant" Content="Lieferant:" Margin="20, 0, 20, 0"></Label>
<TextBox Name="LiefText"
Width="Auto"
Margin="20, 0, 20, 0"
IsEnabled="{Binding Path=LiefEnabled}"
cal:Message.Attach="[Event KeyUp] = [Action KeyUpLief($executionContext)]">
</TextBox>
<Button Name="SucheArtikel"
Content="Suchen"
Width="100" Height="25"
Margin="20, 10,240, 10">
</Button>
<Button x:Name="GesamteListeAnzeigen"
Content="Gesamte Liste anzeigen"
Width="150" Height="26"
Margin="0, -50, 20, 0"
HorizontalAlignment="Right"/>
<main:MultipleSelectionListBox
x:Name="LboxAddArtikel"
SelectionMode="Multiple"
Width="320" Height="220"
Margin="20, 10, 20, 10"
BindableSelectedItems="{Binding Path=MyCollectionOfSelectedIDs}">
</main:MultipleSelectionListBox>
<Button x:Name="FuegeArtikelHinzu"
Content="Hinzufügen"
Width="100" Height="25">
</Button>
</StackPanel>
View2 是绑定到 ViewModel2 的数据。但在向您展示 ViewModel2 之前,我想向您展示我可以在 View2 中做什么:
我从列表框中选择了 3 篇文章,然后单击 view2 底部的按钮将这些文章添加到列表中:
<Button x:Name="FuegeArtikelHinzu" Content="Hinzufügen" Width="100" Height="25"> </Button>
文章被添加到FuegeArtikelHinzu方法viewmodel2中的列表中:
ViewModel2:
public class InventurartikelViewModel : Screen
{
private List<string> _artikelliste = new List<string>();
public List<string> Artikelliste
{
get { return _artikelliste; }
set
{
_artikelliste = value;
OnPropertyChanged("Artikelliste");
}
}
public bool ArtikellisteUpdated()
{
Filled = Artikelliste != null ? true : false;
return Filled;
}
private bool _filled;
public bool Filled
{
get
{
return _filled;
}
set
{
_filled = value;
OnPropertyChanged("Filled");
if(_filled == true)
{
//TO BE IMPLEMENTED
//then invoke ViewModelA's method `ArtikellisteUmformen()`
}
_filled = false; //I believe I would need to set _filled back
//to false to prevent overflow. Otherwise ViewModelA's method
//`ArtikellisteUmformen()` would get invoked over and over again because
//_filled is always true from now on. Is that correct?
}
}
public void FuegeArtikelHinzu()
{
try
{
//This adds only the multiple selected items to a list
var multi = MyCollectionOfSelectedIDs;
int i = 0;
foreach (string item in multi)
{
Artikelliste.Insert(i, item);
i++;
}
MessageBox.Show("Artikel hinzugefügt!"); //ok, all added...
//call `ArtikellisteUpdated()` and set Property `Filled` (=`Artikelliste` is filled) to true
ArtikellisteUpdated(); //true unless null
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Zuerst Artikel auswählen!"); //you must select an article first...
}
}
}
这是我的问题!我需要列表中的选定文章artikelliste IN MY VIEW MODEL1!!!
但是我遇到了死胡同。我听说这可以通过实现 IMessenger 服务来解决,但我不明白它在我的示例中是如何工作的。根据我的示例,我需要做什么才能将artikelliste 传递给ViewModel1?如果您不熟悉 Caliburn Micro,请从头开始或使用框架发布另一个解决方案,我不介意。提前感谢您的帮助!
编辑:
我现在可以在 ViewModel1 中访问 ViewModel2 及其 Artikelliste 属性。但是,我想在 ViewModel2 的 Artikelliste 更新后立即调用 ViewModel1 的方法 ArtikellisteUmformen()。我怎么做?
这就是我想做的:
当
Artikelliste已被填充时,您可以在 ViewModel2 上调用一个事件,例如 ArtikelListeUpdated。 ViewModel1 侦听该事件并在必要时对其做出反应。您甚至不需要该事件,以防您不必立即对其做出反应。
【问题讨论】:
-
第一个问题,只要windowManager没有暴露UI元素就不会违反MVVM。如果您想要选定的项目,请在列表框中为每个项目添加一个命令,以将它们添加到您的 ViewModel 的集合中。因为您拥有视图模型的实例,所以您将可以访问这些项目。简单
-
我更新了我的问题。除了最后一步(要点),我做了@maxx313 的建议。我不知道如何实现事件和监听器。以前从来没有这样做过。能否请你帮忙?请在我给定的项目中实施最后一个要点。这对我来说很重要!
-
问题更新:现在我需要的最后一步是:当 ViewModel2 的 Property
Filled为 true 时,调用 ViewModel1 的方法ArtikellisteUmformen()。但我无法从 ViewModel2 访问 VIewModel1。我如何从 VIEWMODEL1 监听到 VIEWMODEL2 的属性FILLED并在FILLED == TRUE时调用ARTIKELLISTEUMFORMEN()?????????????????????????
标签: c# wpf mvvm caliburn.micro