wpf – 通过MVVM绑定UserControl依赖属性

我有一个包含UserControl的MainWindow,它们都是用MVVM模式实现的.
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中声明DependencyProperty TextInControl.

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

 

posted on   jack_Meng  阅读(5033)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
历史上的今天:
2017-02-24 系列文章----.Net程序员学用Oracle系列
2017-02-24 PLSQL Developer 攻略
2014-02-24 读写XML文档时,去掉新增加节点的“空命名空间”(xmlns=””)

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示

喜欢请打赏

扫描二维码打赏

支付宝打赏

主题色彩