我刚刚开始学习MVVM,我想知道当我单击UserControl内部的按钮时想要从MainWindow更改内容时的最佳做法是什么。
这是UserControl,其中包含我将要单击的按钮。当我单击生成的IconButton时,我希望能够将MainGrid更改为包含我的IconModel信息的网格。
为澄清起见,我希望网格显示图标的名称,描述,用户名,密码,并具有一个使用Path可以打开程序或网站的按钮。 Icon类位于下面发布的IconModel.cs中。
IconView.xaml
<UserControl x:Class="ProgramManager.Views.IconView"
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:ProgramManager"
xmlns:viewModel="clr-namespace:ProgramManager.ViewModel"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.DataContext>
<viewModel:IconViewModel/>
</UserControl.DataContext>
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding Path = Icons}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Name="IconButton" Style="{StaticResource IconButtonStyle}" Content="{Binding Path = Initial, Mode = OneWay}" Click="Button_Click">
<Button.ToolTip>
<ToolTip Content="{Binding Path = Name, Mode = TwoWay}"/>
</Button.ToolTip>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</UserControl>
MainWindow.xaml
<Window x:Class="ProgramManager.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ProgramManager"
xmlns:views="clr-namespace:ProgramManager.Views"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid Name="MainGrid" Grid.Column="1">
</Grid>
</Grid>
</Window>
作为参考,这是我的IconModel和IconViewModel类。
IconModel.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Xml.Serialization;
namespace ProgramManager.Model
{
public class IconModel { }
[XmlRoot(ElementName = "Icons", IsNullable = true, DataType = "string")]
[XmlType(AnonymousType = true)]
[XmlInclude(typeof(ProgramIcon))]
[XmlInclude(typeof(WebsiteIcon))]
public class Icon : IComparable<Icon>, IComparer<Icon>, INotifyPropertyChanged
{
private string name;
private string description;
private string path;
private string username;
private string password;
[XmlElement("Name")]
public string Name
{
get { return name; }
set
{
if (name != value)
{
name = value;
RaisePropertyChanged("Name");
}
}
}
[XmlElement("Description")]
public string Description
{
get { return description; }
set
{
if (description != value)
{
description = value;
RaisePropertyChanged("Description");
}
}
}
[XmlElement("Path")]
public string Path
{
get { return path; }
set
{
if (path != value)
{
path = value;
RaisePropertyChanged("Path");
}
}
}
[XmlElement("Username")]
public string Username
{
get { return username; }
set
{
if (username != value)
{
username = value;
RaisePropertyChanged("Username");
}
}
}
[XmlElement("Password")]
public string Password
{
get { return password; }
set
{
if (password != value)
{
password = value;
RaisePropertyChanged("Password");
}
}
}
public string Initial {
get
{
return this.Name.Substring(0, 1).ToUpper();
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
public int Compare(Icon x, Icon y)
{
return (x.Equals(null) || y.Equals(null)) ? 0 : x.CompareTo(y);
}
public int CompareTo(Icon other)
{
return string.Compare(this.Name, other.Name);
}
}
public class ProgramIcon : Icon { }
public class WebsiteIcon : Icon { }
}
IconViewModel.cs
using ProgramManager.Helpers;
using ProgramManager.Model;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
namespace ProgramManager.ViewModel
{
public class IconViewModel : INotifyPropertyChanged
{
private static readonly List<Icon> iconsList;
private ObservableCollection<Icon> icons;
public ObservableCollection<Icon> Icons
{
get { return icons; }
set
{
if (icons != value)
{
icons = value;
RaisePropertyChanged("Icons");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
public IconViewModel()
{
LoadIcons();
}
static IconViewModel()
{
if (!Directory.Exists(Constants.ResourcesDirectory))
{
Directory.CreateDirectory(Constants.ResourcesDirectory);
}
iconsList = XmlDataStorage.GetList<Icon>(Constants.IconsFilePath);
}
public void LoadIcons()
{
ObservableCollection<Icon> icons = new ObservableCollection<Icon>();
foreach(var icon in iconsList)
{
icons.Add(icon);
}
Icons = icons;
}
public void AddIcon(Icon icon)
{
iconsList.Add(icon);
iconsList.Sort();
XmlDataStorage.SaveToXml(Constants.IconsFilePath, iconsList);
LoadIcons();
}
}
}
我尝试从IconView.xaml访问MainWindow中的IconButton,但是我似乎不知道该怎么做。
感谢您的帮助,谢谢!
答案 0 :(得分:0)
您可以访问Application.Current.MainWindow
之类的主窗口。
对于MVVM解决方案,您可以执行以下操作(理解这个想法,我没有对此进行编译):
在MainWindow.xaml内部:
<Label DataContext="{IconViewModel }" Content={Binding YourProperty}/>
我的意思是,您可以将标签的数据上下文设置为IconViewModel,并将其绑定到IconViewModel类的属性。
答案 1 :(得分:0)
为什么不将IconView.xaml更改为ContentTemplate?并且将IconButton绑定依赖项属性。以便可以在任何地方操作IconButton。包括MainWindow。