gpt4 book ai didi

c# - 将 UserControl 的 SelectedValue 绑定(bind)到 ViewModel

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

在我的解决方案中;我有两个项目:一个是 WPF 用户控件库,另一个是 WPF 应用程序。

用户控件非常简单;它是一个标签和一个组合框,将显示已安装的打印机。

在 WPF 应用程序中;我想使用这个用户控件。所选值将存储在用户设置中。

我遇到的问题是我似乎无法使正确的绑定(bind)工作。我需要做的是能够在加载 MainWindow 时设置 UserControl 的 SelectedValue;以及在我保存设置时访问 UserControl 的 SelectedValue。

我的代码在下面,有人能给我指出正确的方向吗?

打印队列用户控件:

<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>

打印队列代码隐藏:

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();
}
}

打印队列 View 模型:

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
}));
}
}

主窗口:

<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>

主窗口 View 模型:

public class MainWindowViewModel : ViewModelBase
{
private string printerName;

public string PrinterName
{
get { return printerName; }
set
{
printerName = value;
NotifyPropertyChanged(() => PrinterName);
}
}

public MainWindowViewModel()
{
PrinterName = "Lexmark T656 PS3";
}
}

最佳答案

库中的控件需要公开您可以在 View 中绑定(bind)的 DependencyProperties。就像 WPF 的 TextBox 公开了一个 Text 属性。

您的 PrintQueue 控件不会公开任何内容,而是将其所有状态保存在一个外部任何人都无法访问的 View 模型中。您的 MainWindowViewModel 无法获取 PrintQueueViewModel 中的内容。

您需要在 PrintQueue xaml 的代码后面将 SelectedPrinterName 公开为 DependencyProperty。然后在 MainWindow.xaml 中,您可以将其绑定(bind)到 MainWindowViewModel.PrinterName

如果您想一直使用 ViewModel,则 MainWindowViewModel 应该自己创建 PrintQueueViewModel,以便它可以访问其中的属性。

根据您的更新/评论:

不幸的是,DependencyProperties 不是那样工作的。 getters/setters 甚至大部分时间都不会被使用,它们应该只更新属性本身。你现在有点介于两个世界之间。

如果我处在您的位置,并且假设您可以更改库以便 PrintQueue.xaml 在 View 中没有硬编码的 VM 实例,我会自己创建 PrintQueueViewModel。这就是 MVVM 应该如何工作的:

View 模型:

public class MainWindowViewModel : ViewModelBase
{
public PrintQueueViewModel PrintQueue { get; private set; }

public MainWindowViewModel()
{
PrintQueue = new PrintQueueViewModel();
PrintQueue.SelectedPrinterName = "Lexmark T656 PS3";
}
}

查看:

<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>

同样,控件库通常没有 View 模型,并且通过依赖属性公开它们的状态,因为它们被设计为在 XAML 中使用。

组件库可能公开 View 模型,但在那种情况下它们不会在 View 中对 View 模型进行硬编码。

库是你写的吗?如果不是,作者希望人们如何使用它?

关于c# - 将 UserControl 的 SelectedValue 绑定(bind)到 ViewModel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22044577/

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