[英]wpf c# data binding to set string using property of viewModel object
我試圖解決這個問題很多小時:
我有一個名為NewMazeGrid
的網格用戶自定義控件,我想將其用作MainWindow
的控件。 MainWindow
包含MazeViewModel
(mazeVM成員)。
當屬性MazeViewModel:MySingleplay
更改時,我嘗試設置網格的值。 (我正在使用INotifyPropertyChanged
,它工作得很好。我想,問題出在最終綁定中)代碼:
這是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>
我在裝訂線上收到此錯誤: 值不能為null。
總結:可以在ctor中初始化窗口,但是當屬性更改時,它不會進入Order屬性設置器中。 因此,我的網格永遠不會改變。
在這種情況下,綁定的正確語法應該是什么? 如何將其綁定到正確的屬性?
WPF可能不會調用依賴項屬性的CLR包裝器,而只是直接調用基礎DependencyObject的GetValue
和SetValue
方法。 這就是為什么除了GetValue和SetValue調用外不應有任何邏輯的原因。
XAML加載和依賴項屬性中對此進行了說明:
由於XAML處理器當前針對屬性設置的行為的WPF實現完全繞過了包裝器,因此您不應為自定義依賴項屬性在包裝器的集合定義中添加任何其他邏輯。 如果將這樣的邏輯放在集合定義中,則當在XAML中而不是在代碼中設置屬性時,將不會執行該邏輯。
同樣,從XAML處理獲得屬性值的XAML處理器的其他方面也使用GetValue而不是使用包裝器。 因此,您還應該避免在GetValue調用之外的get定義中進行任何其他實現。
要獲得有關屬性值更改的通知,可以按屬性元數據注冊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;
}
也就是說,也不需要在單向綁定上設置UpdateSourceTrigger=PropertyChanged
。 它僅對雙向(或單向源)綁定有效:
<Controls:NewMazeGrid Order="{Binding MySingleplay}"/>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.