MainWindowVM具有我想要綁定到UserControl1VM中的屬性的屬性.但這不起作用.
這里是一些代碼(viewmodels使用某種mvvm框架,在ViewModelBase類中實現INotifyPropertyChanged,但希望沒問題):
MainWindow.xaml:
<Window x:Class="DPandMVVM.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DPandMVVM"
Title="MainWindow" Height="300" Width="300">
<Grid>
<local:UserControl1 TextInControl="{Binding Text}" />
</Grid>
</Window>
CodeBehind MainWindow.xaml.cs:
using System.Windows;
namespace DPandMVVM
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowVM();
}
}
}
MainWindow-ViewModel MainWindowVM.cs:
namespace DPandMVVM
{
public class MainWindowVM : ViewModelBase
{
private string _text;
public string Text { get { return _text; } }
public MainWindowVM()
{
_text = "Text from MainWindowVM";
}
}
}
在這里UserControl1.xaml:
<UserControl x:Class="DPandMVVM.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="300" d:DesignWidth="300">
<Grid>
<TextBlock Text="{Binding TextInTextBlock}" />
</Grid>
</UserControl>
Codebehind UserControl1.xaml.cs:
using System.Windows.Controls;
namespace DPandMVVM
{
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
DataContext = new UserControl1VM();
}
}
}
和Viewmodel UserControl1VM.cs:
using System.Windows;
namespace DPandMVVM
{
public class UserControl1VM : DependencyObject
{
public UserControl1VM()
{
TextInControl = "TextfromUserControl1VM";
}
public string TextInControl
{
get { return (string)GetValue(TextInControlProperty); }
set { SetValue(TextInControlProperty, value); }
}
public static readonly DependencyProperty TextInControlProperty =
DependencyProperty.Register("TextInControl", typeof(string), typeof(UserControl1VM));
}
}
使用此星座,無法在MainWindow.xaml中找到DP. 我究竟做錯了什么?
在UserControl1中移動DP的聲明.
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public string TextInControl
{
get { return (string)GetValue(TextInControlProperty); }
set { SetValue(TextInControlProperty, value); }
}
public static readonly DependencyProperty TextInControlProperty =
DependencyProperty.Register("TextInControl", typeof(string),
typeof(UserControl1));
}
其次,你將UserControl的DataContext外部設置為UserControl1VM,
public UserControl1()
{
InitializeComponent();
DataContext = new UserControl1VM(); <-- HERE (Remove this)
}
所以WPF綁定引擎在UserControl1VM中尋找屬性Text而不是MainWindowVM.刪除設置DataContext並將UserControl1的XAML更新為:
<UserControl x:Class="DPandMVVM.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="300" d:DesignWidth="300"
x:Name="userControl1">
<Grid>
<TextBlock Text="{Binding TextInTextBlock, ElementName=userControl1}" />
</Grid>
</UserControl>
通過在UserControl上設置x:Name,使用ElementName綁定DP.
UPDATE
如果您希望UserControl的ViewModel完好無損,則必須更新MainWindow中的綁定.
顯式告訴WPF綁定引擎在MainWindow的DataContext中使用ElementName查找屬性,如下所示:
<local:UserControl1 TextInControl="{Binding DataContext.Text,
ElementName=mainWindow}" />
為此,您需要在窗口根級別設置x:Name =“mainWindow”.
出處:http://www.voidcn.com/article/p-udpyjbsd-bue.html
注意: 在使用MVVM框架的時候,如果在vm里獲取UserControl的綁定數據,需要使用雙向綁定"{Binding PageIndex,Mode=TwoWay}"
======================================================================
另外在提供一個在界面上使用ContentControl控件來綁定UserControl對象的方法。
界面元素:
<Window.DataContext> <localVM:BarViewModel /> </Window.DataContext> <Grid> <StackPanel Height="30" Margin="0,300,2,105"> <ContentControl Content="{Binding StatusBar}"></ContentControl> </StackPanel> </Grid>
對應的BarViewModel類:
public class BarViewMod : INotifyPropertyChanged { public BarViewMod() { StatusBar = new View.UserCtrl.StatusBarView(); } public object StatusBar { get; set; } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName]string propertyName = "") { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } }
StatusBarView對於界面元素
<UserControl x:Class="WpfApp1.View.UserCtrl.StatusBarView" 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:local="clr-namespace:WpfApp1.View.UserCtrl" xmlns:uc="clr-namespace:WpfApp1.VM" mc:Ignorable="d" d:DesignHeight="25" d:DesignWidth="800"> <UserControl.DataContext> <uc:StatusBarViewModel></uc:StatusBarViewModel> </UserControl.DataContext> <Grid> <StatusBar x:Name="MyStatusBar"> <StatusBar.ItemsPanel> <ItemsPanelTemplate> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="100" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="100" /> </Grid.ColumnDefinitions> </Grid> </ItemsPanelTemplate> </StatusBar.ItemsPanel> <StatusBarItem> <TextBlock Name="lbMsg" Text="{Binding TestMsg}" /> </StatusBarItem> <Separator Grid.Column="1" /> <StatusBarItem Grid.Column="2"> <TextBlock Text="http://www.baidu.com/file.txt" /> </StatusBarItem> <Separator Grid.Column="3" /> <StatusBarItem Grid.Column="4"> <ProgressBar Value="0" Width="90" Height="16" /> </StatusBarItem> </StatusBar> </Grid> </UserControl>
StatusBarView對應的ViewModel類:
namespace WpfApp1.VM { using System.ComponentModel; using System.Runtime.CompilerServices; using System.Windows; public class StatusBarViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName]string propertyName = "") { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } public string TestMsg { get; set; } = "test...."; } }
如果是使用了其他框架的,可以依照框架修改,如下面是使用了IOC框架的,則在主界面的VM中構造函數中創建UserControl對象:
StatusBar = _serviceProvider.GetRequiredService<UserCtrl.StatusBarViewModel>();