简体   繁体   English

具有图像属性的WPF UserControl

[英]WPF UserControl with Image Property

I have a UserControl Library containing a user control to make a custom title bar for windows. 我有一个UserControl库,其中包含一个为Windows创建自定义标题栏的用户控件。 I have given this title bar two dependency properties - Title and Icon, which I would like to be able to set when I use the control through a DLL. 我给了这个标题栏两个依赖属性-Title和Icon,当我通过DLL使用控件时,我希望能够对其进行设置。

I have got the title working correctly, so that when I set a Title property of the Window's ViewModel, it is populated into the title bar. 我已经使标题正常工作,因此,当我设置Window的ViewModel的Title属性时,它会填充到标题栏中。 However, I cannot get the image to do the same. 但是,我无法使图像执行相同的操作。

I have tried all sorts of variations, and read an entire course on using dependency properties, but I just can't seem to get the image to show. 我尝试了各种变体,并阅读了有关使用依赖项属性的整个课程,但似乎无法显示该图像。 I have tried using ImageSource properties, Project Resources, and Images, but all I get is a blank. 我已经尝试过使用ImageSource属性,Project Resources和Images,但是得到的只是空白。 Can you point me in the right direction to fix the issue? 您能指出我正确的方向来解决此问题吗?

Here is the xaml for the usercontrol (I Read that I had to use the TemplatedParent RelativeSource for the DP, so that is put in - I believe that this will refer to the MainViewModel in the implementation): 这是用于usercontrol的xaml(我读到我必须对DP使用TemplatedParent RelativeSource,所以将其放进去-我相信这将引用实现中的MainViewModel):

<UserControl x:Class="WPFLibrary.User_Controls.TitleBar"
             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">
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/WPFLibrary;component/Styles/Buttons.xaml"/>
                <ResourceDictionary Source="pack://application:,,,/WPFLibrary;component/Styles/Gradients.xaml"/>
                <ResourceDictionary Source="pack://application:,,,/WPFLibrary;component/Styles/Text.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>
    <DockPanel VerticalAlignment="Top" Grid.Row="0" Grid.ColumnSpan="3"
               MouseDown="TitleBar_MouseDown"
               DataContext="{Binding}"
               Background="{StaticResource WindowTitleBar}">
        <Grid Grid.Row="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="5"/>
                <ColumnDefinition Width="30"/>
                <ColumnDefinition Width="5"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="90"/>
            </Grid.ColumnDefinitions>
            <Image Grid.Column="1" Source="{Binding Icon,RelativeSource={RelativeSource TemplatedParent}}"/>
            <TextBlock x:Name="Title_Bar"
                       Grid.Column="3"
                       Text="{Binding Title}"
                       Style="{StaticResource Text_WindowTitle}">
            </TextBlock>
            <!--StackPanel Containing the buttons excluded for SO Question-->
        </Grid>
    </DockPanel>
</UserControl>

and here is the code behind for the same control (Following from some other SO answers, I have tried using project resources and ImageSource for the Image property, but to no avail): 这是相同控件的代码(根据其他一些答案,我尝试将项目资源和ImageSource用于Image属性,但无济于事):

using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace WPFLibrary.User_Controls
{
    /// <summary>
    /// Interaction logic for TitleBar.xaml
    /// </summary>
    public partial class TitleBar : UserControl, INotifyPropertyChanged
    {

        public Image Icon
        {
            get { return (Image)GetValue(IconProperty); }
            set { SetValue(IconProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Icon.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IconProperty = DependencyProperty.Register("Icon", typeof(Image), typeof(TitleBar) );

        private static PropertyChangedEventArgs _stateChange = new PropertyChangedEventArgs("Windowstate");
        public WindowState _windowState;

        public WindowState Windowstate
        {
            get
            { return _windowState; }
            set
            {
                _windowState = value;
                NotifyChange(_stateChange);
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyChange(PropertyChangedEventArgs e)
        {
            PropertyChanged?.Invoke(this, e);
        }

        public TitleBar()
        {
            InitializeComponent();
        }

        //Button Click Methods excluded for SO question
    }
}

The xaml for the implementation of the usercontrol is like this - I set the binding to the MainViewModel; 用于实现usercontrol的xaml是这样的-我将绑定设置为MainViewModel; that has a constructor that sets the properties. 具有用于设置属性的构造函数。

<Window x:Class="Demo_of_WPF_Library.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:uc="clr-namespace:WPFLibrary.User_Controls;assembly=WPFLibrary"
        xmlns:vm="clr-namespace:Demo_of_WPF_Library.ViewModel"
        mc:Ignorable="d"
        WindowStyle="None"
        BorderBrush="{StaticResource WindowBackgroundBrush}"
        x:Name="Main_Window"
        WindowState="{Binding Windowstate,ElementName=Titlebar}"
        Background="{StaticResource WindowBackgroundBrush}"
        Height="300" Width="800">
    <Window.DataContext>
        <vm:MainView_Model/>
    </Window.DataContext>
    <Grid>
        <uc:TitleBar Name="Titlebar" Icon="{Binding Icon}">
        </uc:TitleBar>
    </Grid>
</Window>

Here is the code for the MainView_Model that holds the properties for the mainwindow: 这是MainView_Model的代码,其中包含mainwindow的属性:

namespace Demo_of_WPF_Library.ViewModel
{
    public class MainView_Model
    {
        private string _title;
        public string Title
        {
            get { return _title; }
            set { _title = value; }
        }
        private Image _icon;

        public Image Icon
        {
            get { return _icon; }
            set { _icon = value; }
        }

        public MainView_Model()
        {
            Title = "Demo WPF Library";
            Icon = new Image();
            Icon.Source = new BitmapImage(new Uri("/View/Images/IsItOk.ico",UriKind.Relative));
        }
    }
}

Finally, here is the code behind the mainwindow, which sets the binding to the MainViewModel and initialises the window: 最后,这是mainwindow背后的代码,该代码设置对MainViewModel的绑定并初始化窗口:

public partial class MainWindow : Window
{
    public MainView_Model MainView { get; set; }
    public MainWindow()
    {
        MainView = new MainView_Model();
        DataContext = MainView;
        InitializeComponent();
    }
}

I honestly cannot see what it is that is missing / wrong here and I have read loads of articles, questions and answers that basically seem to say that I'm doing things in the correct way... So what on earth is wrong? 老实说,我看不到这里缺少什么/错了,我已经读了很多文章,问题和答案,基本上似乎是在说我在以正确的方式做事……那么到底什么是错的?

Your binding is wrong. 您的绑定错误。 You shouldn't use a TemplatedParent if you have no template. 如果没有TemplatedParent则不应使用TemplatedParent Use: 采用:

xmlns:local="clr-namespace:WPFLibrary.User_Controls"
<Image Grid.Column="1" Source="{Binding Icon, RelativeSource={RelativeSource AncestorType=local:TitleBar}}"/>

The problem is you've got an Image in your XAML which is trying to bind to an Image in your view model. 问题是您的XAML中有一个试图绑定到视图模型中的Image的Image。 GUI objects like Image have no place in your view model layer, change your Icon dependency property to be of type ImageSource and bind your XAML image to that instead. 诸如Image类的GUI对象在视图模型层中没有位置,请将Icon依赖项属性更改为ImageSource类型,然后将XAML图像绑定到该类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM