gpt4 book ai didi

c# - wpf c# 数据绑定(bind)以使用 viewModel 对象的属性设置字符串

转载 作者:太空宇宙 更新时间:2023-11-03 15:21:49 24 4
gpt4 key购买 nike

我花了很多时间试图解决这个问题:

我有名为 NewMazeGrid 的用户自定义网格控件,我想将它用作 MainWindow 中的控件。 MainWindow 包含 MazeViewModel(mazeVM 成员)。

当属性 MazeViewModel:MySingleplay 发生变化时,我正在尝试设置网格的值。(我正在为它使用 INotifyPropertyChanged,它工作得很好。我猜,问题出在最后的绑定(bind)中)代码:

这是属性MazeViewModel:MySingleplay getter:

public string MySingleplay
{
get
{
if (myModel.MySingleplay == null)
{
return "";
} else
{
return myModel.MySingleplay.ToString();//works perfect
}
}
}

这是 NewMazeGrid.xaml.cs:

namespace VisualClient.View.controls
{
public partial class NewMazeGrid : UserControl
{
private MazePresentation myMaze;
private string order; //dont really use it

//Register Dependency Property

public static readonly DependencyProperty orderDependency =
DependencyProperty.Register("Order", typeof(string), typeof(NewMazeGrid));

public NewMazeGrid()
{
myMaze = new MazePresentation();
InitializeComponent();
DataContext = this;
lst.ItemsSource = myMaze.MazePuzzleLists;
}

public string Order
{
get
{
return (string)GetValue(orderDependency);
}
set
{
SetValue(orderDependency, value);
myMaze.setPresentation(value); //(parsing string into matrix)
}
}
}
}

这是 MainWindow.xaml.cs:

public partial class MainWindow : Window
{
private MazeViewModel mazeVM;

public MainWindow()
{
InitializeComponent();

mazeVM = new MazeViewModel(new ClientMazeModel(new TCPClientConnection()));
DataContext = mazeVM;

mazeVM.connectToServer();
}

private void bu_Click(object sender, RoutedEventArgs e)
{
bool isC = mazeVM.isConnected();
mazeVM.openSingleplayGame("NewMaze");//works perfect
}

这是 MainWindow.xaml:

<Window x:Class="VisualClient.View.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:Controls ="clr-namespace:VisualClient.View.controls"
xmlns:vm ="clr-namespace:VisualClient.ViewModel"
xmlns:local="clr-namespace:VisualClient.View"

mc:Ignorable="d"
Title="Main Window" Height="350" Width="525" MinWidth="900" MinHeight="600">
<WrapPanel >
<Button Name ="bu" Content="Click_Me" Click="bu_Click"/>
<Grid Name="myGrid">
<Controls:NewMazeGrid Order="{Binding MySingleplay, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</WrapPanel>
</Window>

我在绑定(bind)行上收到此错误:值不能为空。

总结:它在 ctor 中很好地初始化窗口,但是当属性更改时,它不会进入 Order 属性 setter 。因此我的网格永远不会改变。

在这种情况下,正确的绑定(bind)语法应该是什么?我如何将它绑定(bind)到正确的属性?

Folders hierarchy explorer

最佳答案

WPF 可能不会调用依赖属性的 CLR 包装器,而只是直接调用底层 DependencyObject 的 GetValueSetValue 方法。这就是为什么除了 GetValue 和 SetValue 调用之外不应该有任何逻辑。

这在 XAML Loading and Dependency Properties 中有解释:

Because the current WPF implementation of the XAML processor behavior for property setting bypasses the wrappers entirely, you should not put any additional logic into the set definitions of the wrapper for your custom dependency property. If you put such logic in the set definition, then the logic will not be executed when the property is set in XAML rather than in code.

Similarly, other aspects of the XAML processor that obtain property values from XAML processing also use GetValue rather than using the wrapper. Therefore, you should also avoid any additional implementation in the get definition beyond the GetValue call.


要获得有关属性值更改的通知,您可以注册 PropertyChangedCallback通过属性元数据。另请注意,DependencyProperty 字段有一个命名约定。您的应称为 OrderProperty:

public static readonly DependencyProperty OrderProperty =
DependencyProperty.Register(
"Order", typeof(string), typeof(NewMazeGrid),
new PropertyMetadata(OnOrderChanged));

public string Order
{
get { return (string)GetValue(OrderProperty); }
set { SetValue(OrderProperty, value); }
}

private static void OnOrderChanged(
DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
((NewMazeGrid)obj).myMaze.setPresentation((string)e.NewValue);
}

除此之外,你不能设置

DataContext = this;

NewMazeGrid 的构造函数中。这有效地阻止了从父窗口继承 DataContext,因此 {Binding MySingleplay} 将不起作用。除非在特殊情况下,否则您永远不要显式设置 UserControl 的 DataContext。

因此,从构造函数中删除 DataContext 赋值:

public NewMazeGrid()
{
myMaze = new MazePresentation();
InitializeComponent();
lst.ItemsSource = myMaze.MazePuzzleLists;
}

也就是说,也没有必要在单向绑定(bind)上设置 UpdateSourceTrigger=PropertyChanged。它仅对双向(或单向源)绑定(bind)有效:

<Controls:NewMazeGrid Order="{Binding MySingleplay}"/>

关于c# - wpf c# 数据绑定(bind)以使用 viewModel 对象的属性设置字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37062594/

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