从另一个xaml更改xaml按钮的属性

时间:2015-08-21 17:31:05

标签: c# xaml silverlight mvvm

我是Silverlight和MVVM的新手,我正在尝试从应用程序内的另一个xaml更改一个xaml的Button.IsEnabled

我试图创建一个类,但我不确定我是否正确使用它...

using System.ComponentModel;

namespace Reporting.Models
{
public class DataSourceValidation : INotifyPropertyChanged
{
    private bool _isSaveEnabled;

    public bool IsSaveEnabled
    {
        get
        {
            return _isSaveEnabled;
        }
        set
        {
            _isSaveEnabled = value;
            RaisedPropertyChanged("IsSaveEnabled");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void RaisedPropertyChanged(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
}

}

Diagram of my problem

我非常感谢一个解释和例子。我一直在寻找,但它没有完全点击我如何将控件绑定到模型然后从另一个xaml.cs更改该值...提供我甚至正在考虑这个正确的方法。

如果我需要提供更多信息,请询问。谢谢你的时间。

1 个答案:

答案 0 :(得分:1)

如果你不想快速完成它(没有好的解决方案)那么你可以使用静态属性来实现这一点:

ExampleA.xaml.cs中创建以下属性:

public static ExampleA CurrentInstance { get; private set; }

并在ExampleA的构造函数中(我将假设该类的名称为ExampleA):

public ExampleA()
{
    this.InitializeComponent();
    CurrentInstance = this;
}

然后在您的ExampleB班级LostFocus方法中

if (ExampleA.CurrentInstance != null)
{
     var button = ExampleA.CurrentInstance.FindName("OKButton") as Button;
     if (button != null)
     {
         button.IsEnabled = true;
     }
}

另一方面,我不知道你的类是如何构建的以及这些XAML文件是如何相关的,但是一个很好的通用解决方案是使用Event Aggregator模式:

我在这里使用来自EventAggregator MVVM框架的Caliburn.Micro类的略微修改版本:

namespace Caliburn.Micro
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;

    /// <summary>
    ///   A marker interface for classes that subscribe to messages.
    /// </summary>
    public interface IHandle { }

    /// <summary>
    ///   Denotes a class which can handle a particular type of message.
    /// </summary>
    /// <typeparam name = "TMessage">The type of message to handle.</typeparam>
    public interface IHandle<TMessage> : IHandle
    {
        /// <summary>
        ///   Handles the message.
        /// </summary>
        /// <param name = "message">The message.</param>
        void Handle(TMessage message);
    }

    /// <summary>
    ///   Enables loosely-coupled publication of and subscription to events.
    /// </summary>
    public interface IEventAggregator
    {
        /// <summary>
        ///   Gets or sets the default publication thread marshaller.
        /// </summary>
        /// <value>
        ///   The default publication thread marshaller.
        /// </value>
        Action<System.Action> PublicationThreadMarshaller { get; set; }

        /// <summary>
        ///   Subscribes an instance to all events declared through implementations of <see cref = "IHandle{T}" />
        /// </summary>
        /// <param name = "instance">The instance to subscribe for event publication.</param>
        void Subscribe(object instance);

        /// <summary>
        ///   Unsubscribes the instance from all events.
        /// </summary>
        /// <param name = "instance">The instance to unsubscribe.</param>
        void Unsubscribe(object instance);

        /// <summary>
        ///   Publishes a message.
        /// </summary>
        /// <param name = "message">The message instance.</param>
        /// <remarks>
        ///   Uses the default thread marshaller during publication.
        /// </remarks>
        void Publish(object message);

        /// <summary>
        ///   Publishes a message.
        /// </summary>
        /// <param name = "message">The message instance.</param>
        /// <param name = "marshal">Allows the publisher to provide a custom thread marshaller for the message publication.</param>
        void Publish(object message, Action<System.Action> marshal);
    }

    /// <summary>
    ///   Enables loosely-coupled publication of and subscription to events.
    /// </summary>
    public class EventAggregator : IEventAggregator
    {

        /// <summary>
        /// The singleton instance.
        /// </summary>
        public static EventAggregator Instance = new EventAggregator();

        /// <summary>
        ///   The default thread marshaller used for publication;
        /// </summary>
        public static Action<System.Action> DefaultPublicationThreadMarshaller = action => action();

        readonly List<Handler> handlers = new List<Handler>();

        /// <summary>
        ///   Initializes a new instance of the <see cref = "EventAggregator" /> class.
        /// </summary>
        public EventAggregator()
        {
            PublicationThreadMarshaller = DefaultPublicationThreadMarshaller;
        }

        /// <summary>
        ///   Gets or sets the default publication thread marshaller.
        /// </summary>
        /// <value>
        ///   The default publication thread marshaller.
        /// </value>
        public Action<System.Action> PublicationThreadMarshaller { get; set; }

        /// <summary>
        ///   Subscribes an instance to all events declared through implementations of <see cref = "IHandle{T}" />
        /// </summary>
        /// <param name = "instance">The instance to subscribe for event publication.</param>
        public virtual void Subscribe(object instance)
        {
            lock (handlers)
            {
                if (handlers.Any(x => x.Matches(instance)))
                    return;

                handlers.Add(new Handler(instance));
            }
        }

        /// <summary>
        ///   Unsubscribes the instance from all events.
        /// </summary>
        /// <param name = "instance">The instance to unsubscribe.</param>
        public virtual void Unsubscribe(object instance)
        {
            lock (handlers)
            {
                var found = handlers.FirstOrDefault(x => x.Matches(instance));

                if (found != null)
                    handlers.Remove(found);
            }
        }

        /// <summary>
        ///   Publishes a message.
        /// </summary>
        /// <param name = "message">The message instance.</param>
        /// <remarks>
        ///   Does not marshall the the publication to any special thread by default.
        /// </remarks>
        public virtual void Publish(object message)
        {
            Publish(message, PublicationThreadMarshaller);
        }

        /// <summary>
        ///   Publishes a message.
        /// </summary>
        /// <param name = "message">The message instance.</param>
        /// <param name = "marshal">Allows the publisher to provide a custom thread marshaller for the message publication.</param>
        public virtual void Publish(object message, Action<System.Action> marshal)
        {
            Handler[] toNotify;
            lock (handlers)
                toNotify = handlers.ToArray();

            marshal(() =>
            {
                var messageType = message.GetType();

                var dead = toNotify
                    .Where(handler => !handler.Handle(messageType, message))
                    .ToList();

                if (dead.Any())
                {
                    lock (handlers)
                    {
                        foreach (var handler in dead)
                        {
                            handlers.Remove(handler);
                        }
                    }
                }
            });
        }

        protected class Handler
        {
            readonly WeakReference reference;
            readonly Dictionary<Type, MethodInfo> supportedHandlers = new Dictionary<Type, MethodInfo>();

            public Handler(object handler)
            {
                reference = new WeakReference(handler);

                var interfaces = handler.GetType().GetInterfaces()
                    .Where(x => typeof(IHandle).IsAssignableFrom(x) && x.IsGenericType);

                foreach (var @interface in interfaces)
                {
                    var type = @interface.GetGenericArguments()[0];
                    var method = @interface.GetMethod("Handle");
                    supportedHandlers[type] = method;
                }
            }

            public bool Matches(object instance)
            {
                return reference.Target == instance;
            }

            public bool Handle(Type messageType, object message)
            {
                var target = reference.Target;
                if (target == null)
                    return false;

                foreach (var pair in supportedHandlers)
                {
                    if (pair.Key.IsAssignableFrom(messageType))
                    {
                        pair.Value.Invoke(target, new[] { message });
                        return true;
                    }
                }

                return true;
            }
        }
    }
}

在项目中复制此课程。

然后创建一个简单的消息类,它将向任何监听器表示需要启用按钮的消息:

public class EnableButtonMessage
{
}

然后您的ExampleA类需要实现IHandle<EnableButtonMessage>接口(在构造函数中,您需要订阅此类正在接收某种消息,并且Handle方法在执行时收到已注册类型的实际消息,然后启用按钮):

public sealed class ExampleA : UserControl, IHandle<EnableButtonMessage>
{
    ...
    public ExampleA()
    {
        this.InitializeComponent();
        EventAggregator.Instance.Subscribe(this);
    }
    ...
    public void Handle(EnableButtonMessage message)
    {
        this.OKButton.IsEnabled = true;
    }
    ...
}

ExampleB班级&#39;您只需调用LostFocus方法来更改按钮属性:

EventAggregator.Instance.Publish(new EnableButtonMessage());

这是EventAggregator模式的简单实现,然后您可以使用if用于全局中应用程序内任何实体之间的任何消息传递。这是一个强大的模式,当与MVVM一起使用时,可以让您的生活更轻松。