1

私はこのようなものを作成しようとしています -

ここに画像の説明を入力

私は観察可能なポイントのコレクションを持っています。各点には位置と色があります。ポイントの位置や色が変わると(通知の変更が実装されます)、背景のグラデーションを「再描画」したいと思います。現在、スライダーをポイント位置にバインドし、グラデーションを最初に描画する項目コントロールがあります。ここで、「ポイント」で propertychanged イベントが発生したときにビューのコード ビハインドで関数を呼び出す方法を知りたいので、グラデーションを再描画できます。イベントセッターを何らかの方法で使用できるかどうか疑問に思っていますか?

コード ビハインドで propertychanged イベントのサブスクライブを実行できますが、XAML で実行したいですか?

注意してください:他の理由でコードビハインドを手動で再描画するこのアプローチを特に取りたいので、代替ソリューションではなく上記の特定の問題に対する回答を得ることができれば.

4

1 に答える 1

1

PropertyChangedプロパティの値のイベントをサブスクライブする添付プロパティを作成できると思いますDataContext

public static class Props
{
    public static DependencyProperty OnPropertyChangedProperty = DependencyProperty.RegisterAttached(
        "OnPropertyChanged", typeof(PropertyChangedEventHandler), typeof(Props),
        new PropertyMetadata(OnPropertyChangedPropertyChanged));

    public static PropertyChangedEventHandler GetOnPropertyChanged (DependencyObject d)
    {
        return (PropertyChangedEventHandler)d.GetValue(OnPropertyChangedProperty);
    }

    public static void SetOnPropertyChanged (DependencyObject d, PropertyChangedEventHandler value)
    {
        d.SetValue(OnPropertyChangedProperty, value);
    }

    private static void OnPropertyChangedPropertyChanged (DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var inpc = (INotifyPropertyChanged)((FrameworkElement)d).DataContext;
        if (inpc == null)
            throw new ArgumentException("DataContext of the framework element must not be null.");
        var oldChanged = (PropertyChangedEventHandler)e.OldValue;
        if (oldChanged != null)
            inpc.PropertyChanged -= oldChanged;
        var newChanged = (PropertyChangedEventHandler)e.NewValue;
        if (newChanged != null)
            inpc.PropertyChanged += newChanged;
    }
}

使用法:

<Window x:Class="So17382721PropertyChangedXaml.MainWindow" x:Name="root"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:So17382721PropertyChangedXaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <DataTemplate DataType="{x:Type local:Foo}">
            <!-- Here, we subscribe to DataContext.PropertyChanged;
                 handler is defined in the MainWindow class -->
            <Grid local:Props.OnPropertyChanged="{Binding FooPropertyChanged, ElementName=root}">
                <TextBox Text="{Binding Bar, UpdateSourceTrigger=PropertyChanged}"/>
            </Grid>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <ItemsControl ItemsSource="{Binding Foos, ElementName=root}"/>
    </Grid>
</Window>

分離コード:

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;

namespace So17382721PropertyChangedXaml
{
    public partial class MainWindow
    {
        public ObservableCollection<Foo> Foos { get; private set; }

        public MainWindow ()
        {
            Foos = new ObservableCollection<Foo> {
                new Foo { Bar = "1" },
                new Foo { Bar = "2" },
                new Foo { Bar = "3" },
            };
            InitializeComponent();
        }

        private void OnFooPropertyChanged (object sender, PropertyChangedEventArgs e)
        {
            MessageBox.Show(this, string.Format("{0} of {1} changed.", e.PropertyName, sender));
        }

        // Subscribing to non-RoutedEvents in XAML is not straightforward, but we can define a property
        public PropertyChangedEventHandler FooPropertyChanged
        {
            get { return OnFooPropertyChanged; }
        }
    }

    public class Foo : INotifyPropertyChanged
    {
        private string _bar;
        public string Bar
        {
            get { return _bar; }
            set
            {
                _bar = value;
                OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged ([CallerMemberName] string propertyName = null)
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

注: 添付プロパティは、有効期間中に変更されず、既に指定されProps.OnPropertyChangedていることを想定しています。DataContextイベントの処理DataContextChangedは、必要に応じて演習として残します。

于 2013-06-30T06:21:31.087 に答える