Jim*_*m B 3 c# wpf xaml user-controls
在我的解决方案; 我有两个项目:一个是WPF UserControl库,另一个是WPF应用程序.
用户控件非常简单; 它是一个标签和一个组合框,将显示已安装的打印机.
在WPF应用程序中; 我想使用这个usercontrol.所选值将存储在用户设置中.
我遇到的问题是我似乎无法获得正确的绑定工作.我需要做的是能够在MainWindow加载时设置UserControl的SelectedValue; 以及当我去保存我的设置时访问UserControl的SelectedValue.
我的代码在下面,有人能指出我正确的方向吗?
PrintQueue用户控件:
<UserControl x:Class="WpfControls.PrintQueue"
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:wpfControls="clr-namespace:WpfControls"
mc:Ignorable="d">
<UserControl.DataContext>
<wpfControls:PrintQueueViewModel/>
</UserControl.DataContext>
<Grid>
<StackPanel Orientation="Horizontal">
<Label Content="Selected Printer:"></Label>
<ComboBox ItemsSource="{Binding Path=PrintQueues, Mode=OneWay}" DisplayMemberPath="Name" SelectedValuePath="Name" Width="200" SelectedValue="{Binding Path=SelectedPrinterName, Mode=TwoWay}"></ComboBox>
</StackPanel>
</Grid>
</UserControl>
Run Code Online (Sandbox Code Playgroud)
打印队列代码隐藏:
public partial class PrintQueue : UserControl
{
public static readonly DependencyProperty CurrentPrinterNameProperty =
DependencyProperty.Register("CurrentPrinterName", typeof (string), typeof (PrintQueue), new PropertyMetadata(default(string)));
public string CurrentPrinterName
{
get { return (DataContext as PrintQueueViewModel).SelectedPrinterName; }
set { (DataContext as PrintQueueViewModel).SelectedPrinterName = value; }
}
public PrintQueue()
{
InitializeComponent();
DataContext = new PrintQueueViewModel();
}
}
Run Code Online (Sandbox Code Playgroud)
PrintQueue查看型号:
public class PrintQueueViewModel : ViewModelBase
{
private ObservableCollection<System.Printing.PrintQueue> printQueues;
public ObservableCollection<System.Printing.PrintQueue> PrintQueues
{
get { return printQueues; }
set
{
printQueues = value;
NotifyPropertyChanged(() => PrintQueues);
}
}
private string selectedPrinterName;
public string SelectedPrinterName
{
get { return selectedPrinterName; }
set
{
selectedPrinterName = value;
NotifyPropertyChanged(() => SelectedPrinterName);
}
}
public PrintQueueViewModel()
{
PrintQueues = GetPrintQueues();
}
private static ObservableCollection<System.Printing.PrintQueue> GetPrintQueues()
{
var ps = new PrintServer();
return new ObservableCollection<System.Printing.PrintQueue>(ps.GetPrintQueues(new[]
{
EnumeratedPrintQueueTypes.Local,
EnumeratedPrintQueueTypes.Connections
}));
}
}
Run Code Online (Sandbox Code Playgroud)
主窗口:
<Window x:Class="WPFApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfControls="clr-namespace:WpfControls;assembly=WpfControls" xmlns:wpfApp="clr-namespace:WPFApp"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<wpfApp:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<StackPanel>
<wpfControls:PrintQueue CurrentPrinterName="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.PrinterName, Mode=TwoWay}"></wpfControls:PrintQueue>
</StackPanel>
</Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)
主窗口视图模型:
public class MainWindowViewModel : ViewModelBase
{
private string printerName;
public string PrinterName
{
get { return printerName; }
set
{
printerName = value;
NotifyPropertyChanged(() => PrinterName);
}
}
public MainWindowViewModel()
{
PrinterName = "Lexmark T656 PS3";
}
}
Run Code Online (Sandbox Code Playgroud)
库中的控件需要公开可以在视图中绑定的DependencyProperties.就像WPF TextBox公开Text财产一样.
您的PrintQueue控件不会公开任何内容,而是将其所有状态保存在一个外部无法访问的视图模型中.你MainWindowViewModel无法进入内部的东西PrintQueueViewModel.
您需要SelectedPrinterName在PrintQueue xaml后面的代码中公开DependencyProperty.然后在MainWindow.xaml中绑定它MainWindowViewModel.PrinterName.
如果您想要一直使用ViewModels,那么MainWindowViewModel应该创建PrintQueueViewModel自己以便它可以访问其中的属性.
根据您的更新/评论:
不幸的是,DependencyProperties不能那样工作.getter/setter甚至在大多数时候都没有使用,它们应该只更新属性本身.你现在处于两个世界之间.
如果我在你的位置,并假设您可以更改库,以便PrintQueue.xaml在视图中没有硬编码的VM实例,我将自己创建PrintQueueViewModel.这就是MVVM应该如何工作:
视图模型:
public class MainWindowViewModel : ViewModelBase
{
public PrintQueueViewModel PrintQueue { get; private set; }
public MainWindowViewModel()
{
PrintQueue = new PrintQueueViewModel();
PrintQueue.SelectedPrinterName = "Lexmark T656 PS3";
}
}
Run Code Online (Sandbox Code Playgroud)
视图:
<Window x:Class="WPFApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfControls="clr-namespace:WpfControls;assembly=WpfControls" xmlns:wpfApp="clr-namespace:WPFApp"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<wpfApp:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<StackPanel>
<wpfControls:PrintQueue DataContext="{Binding PrintQueue}"/>
</StackPanel>
</Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)
尽管如此,控制库通常没有视图模型,并且通过依赖属性公开它们的状态,因为它们被设计为在XAML中使用.
组件库可能会公开视图模型,但在这种情况下,它们不会在视图中对视图模型进行硬编码.
你写过这个图书馆吗?如果没有,作者是如何期望人们使用它的呢?
| 归档时间: |
|
| 查看次数: |
22861 次 |
| 最近记录: |