在自定義用戶控件上使用DataBinding時出現一個奇怪的問題。 我的UserControl「UserControl1」有一個依賴項屬性LabelText,它在我的UserControl1中設置一個標籤的內容。此外,它還有一個綁定命令「MyCommand」的按鈕。該命令僅顯示一個消息框並在UserControl1ViewModel中實現。我想在MainWindow.xaml中使用綁定到LabelTextFromMainWindow來設置UserControl的LabelText屬性,但是當我這樣做時,我遇到了一個問題它會使用錯誤的DataContext,除非您明確指定它。自定義用戶控件DataBinding問題
這是我的代碼:
public partial class MainWindow : Window
{
private MainWindowViewModel vm;
public MainWindow()
{
InitializeComponent();
DataContext = vm = new MainWindowViewModel();
vm.LabelTextFromMainWindow = "Hallo";
}
}
class MainWindowViewModel : System.ComponentModel.INotifyPropertyChanged
{
#region INotifyPropertyChanged Members
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this,
new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
#endregion
private string myLabel;
public string LabelTextFromMainWindow
{
get { return myLabel; }
set
{
myLabel = value;
OnPropertyChanged("MyLabel");
}
}
}
/////////
<UserControl x:Class="WpfApplication1.UserControl1"
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"
mc:Ignorable="d"
d:DesignHeight="224" d:DesignWidth="300">
<Grid>
<Button Command="{Binding MyCommand}" Content="Button" Height="55" HorizontalAlignment="Left" Margin="166,99,0,0" Name="button1" VerticalAlignment="Top" Width="104" />
<Label Margin="30,99,0,0" Name="label1" Height="55" VerticalAlignment="Top" HorizontalAlignment="Left" Width="101" />
</Grid>
</UserControl>
public partial class UserControl1 : UserControl
{
private UserControl1ViewModel vm;
private static UserControl1 instance;
public UserControl1()
{
InitializeComponent();
instance = this;
DataContext = vm = new UserControl1ViewModel();
}
public string LabelText
{
get { return (string)GetValue(LabelProperty); }
set { SetValue(LabelProperty, value); }
}
public static readonly DependencyProperty LabelProperty =
DependencyProperty.Register("LabelText", typeof(string), typeof(UserControl1), new UIPropertyMetadata(""), OnValidateValueProperty);
private static bool OnValidateValueProperty(object source)
{
if (instance != null)
{
instance.label1.Content = source;
}
return true;
}
}
public class UserControl1ViewModel
{
private DelegateCommand myCommand;
public ICommand MyCommand
{
get
{
if (myCommand == null)
myCommand = new DelegateCommand(new Action<object>(MyExecute),
new Predicate<object>(MyCanExecute));
return myCommand;
}
}
private bool MyCanExecute(object parameter)
{
return true;
}
private void MyExecute(object parameter)
{
MessageBox.Show("Hello World");
}
}
我的主窗口日誌如下:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:my="clr-namespace:WpfApplication1">
<Grid>
<my:UserControl1 LabelText="{Binding
Path=DataContext.LabelTextFromMainWindow,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}}"
HorizontalAlignment="Left"
Margin="114,36,0,0"
x:Name="userControl11"
VerticalAlignment="Top" Height="236" Width="292" />
</Grid>
</Window>
我exspected以下才能正常工作。
LabelText="{Binding Path=LabelTextFromMainWindow}"
但是,我必須寫這一個。
LabelText="{Binding Path=DataContext.LabelTextFromMainWindow,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}}"
爲了讓簡單的綁定正常工作,我需要做些什麼?
感謝你的解釋,我發現了一個更好的解決方案自己。如果我的UserControl1沒有DataContext,但第一個子項(在這種情況下是名爲「DataContextHolder」的Grid),我可以得到我在找的東西。 <用戶控件X:類= 「WpfApplication1.UserControl1」> \t <網格X:名稱= 「DataContextHolder」> \t 用戶控件> 公共部分類的UserControl1:用戶控件 { \t公共的UserControl1() \t { \t \t DataContextHolder。DataContext = new UserControl1ViewModel(); \t} } – BikingGlobetrotter
是的,這是一種破解,但足夠你的問題陳述。 –