2

.NETFramework4.0に切り替えるときに問題が発生しました。Top/LeftおよびWidht/Heightプロパティで双方向バインディングを使用するウィンドウがあります。

viewModelを変更する必要があるときに問題が発生します。

基になるViewModelを変更した後、viewModelに対応するpropertynameでPropertyChangedイベントをトリガーすると、Leftプロパティのバインディングがトリガーされ、ウィンドウが正しいX位置に移動します。しかし、ウィンドウを移動するアクションは「ソースへ」をトリガーし、viewModelのTopプロパティを設定します。 編集:「設定」は行われていませんが、Yバインディングは処理されません。

Height&Widthプロパティと同じ動作。

これが私の問題を示す小さなアプリケーションです。

これがモデルです:

 public class Model : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public Position SelectedPos { get; set; }
        public Position Pos1 { get; set; }
        public Position Pos2 { get; set; }

    public Model( int x, int y, int x2, int y2 )
    {
        Pos1 = new Position( x, y );
        Pos2 = new Position( x2, y2 );
        SelectedPos = Pos1;
    }

    public void Toggle()
    {
        SelectedPos = Pos2;

        if( PropertyChanged != null )
        {
            var e = new PropertyChangedEventArgs( "SelectedPos" );
            PropertyChanged( this, e );
        }
    }
}

public class Position
{
    int _x;
    public int X
    {
        get { return _x; }
        set { _x = value; }
    }

    int _y;
    public int Y
    {
        get { return _y; }
        set { _y = value; }
    }

    public Position( int x, int y )
    {
        X = x;
        Y = y;
    }
}

そしてここにビューがあります:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" 
        Left="{Binding Mode=TwoWay, Path=SelectedPos.X}"
        Top="{Binding Mode=TwoWay, Path=SelectedPos.Y}">
    <Grid>
        <Button Click="Button_Click">Change Position</Button>
    </Grid>
</Window>

そして最後に、コードビハインド:

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        Model model;

        public MainWindow()
        {
            InitializeComponent();
            model = new Model( 5, 5, 500, 500 );
            DataContext = model;
        }

        private void Button_Click( object sender, RoutedEventArgs e )
        {
            model.Toggle();
        }
    }
}

私が知りたかったのは、バインディングを「フリーズ」して、要求したすべてのバインディングの処理が完了するまでエンジンがviewModelを設定しないようにする方法があるかどうかです。または、バインディングをtwoWayからOneWayに短時間切り替えます。

ここでの小さなアプリケーションは、.NET Framework 3.5を使用すると正しく動作しますが、4.0では動作しません。

同じ問題に苦しんでいる人を見つけることができなかったので驚いています、私は何か間違ったことをしていますか?ご回答ありがとうございます。不明な点がございましたら、お気軽にお問い合わせください。

Jean-Loup Kahloun


今朝ログを追加しました(ここに投稿する前に追加する必要があります)。あなたが行ったように、「設定」は行われていませんが、Yバインディングは処理されません。実際にウィンドウの位置を数回切り替えると、動作はさらに奇妙になります。

コードビハインドの使用を避けたかったのですが、ソリューションをテストします(テスト目的でのみ使用したものもあります)。

迅速に回答していただきありがとうございます。コードビハインドのない解決策を見つける時間ができたら、折り返しご連絡いたします。モデルが設定されていないため、奇妙な動作をする「Position」バインディングがトリガーされた直後に、propertychangedイベントでXバインディングとYバインディングを別々にトリガーできる可能性があります。

もう一度ありがとう、私は間違った方向に進んでいました、あなたは私にたくさんの時間を節約しました。

4

1 に答える 1

1

私はあなたの主張に同意するかどうか確信が持てません

しかし、ウィンドウを移動するアクションは「ソースへ」をトリガーし、viewModel の Top プロパティを設定します。

コードを実行したところ、[位置の変更] ボタンをクリックすると、ウィンドウが (5, 5) から (500, 5) に移動することが確認できました。ただし、Clickイベント ハンドラーがウィンドウの値LeftTop値をデバッグ ログに書き込む別のボタンを追加しました。これは、ウィンドウが明らかに(500、500)にあることを報告していることがわかりました。次に、それを少しドラッグし、このボタンをもう一度クリックすると、ウィンドウが (498, 4) にあることが通知されました。

バインディングは正しく機能していると思いますが、何らかの理由で、ウィンドウLeftTopプロパティの両方がバインディングを介してすばやく連続して変更された場合、Windows はウィンドウを移動しません。なぜこれが起こるのかわかりません。特に.NET 3.5で機能する場合、.NET 4のバグである可能性があります。

ウィンドウのプロパティを 内の個々の X 座標と Y 座標にバインドするのではなく、タイプの依存関係プロパティを追加し、Positionそれを直接にバインドすると、ウィンドウが期待どおりに動作することがわかりました。この依存関係プロパティが変更されたとき、ウィンドウのとの値を内のとの値に設定しました。SelectedPosLeftTopSelectedPosLeftTopXYPosition

追加した依存関係プロパティとプロパティ変更コールバックは次のとおりです。

    public Position WindowPosition
    {
        get { return (Position)GetValue(WindowPositionProperty); }
        set { SetValue(WindowPositionProperty, value); }
    }

    public static readonly DependencyProperty WindowPositionProperty =
        DependencyProperty.Register("WindowPosition", typeof(Position), typeof(MainWindow), new PropertyMetadata(WindowPosition_Changed));

    private static void WindowPosition_Changed(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        var mainWindow = obj as MainWindow;
        mainWindow.Left = mainWindow.WindowPosition.X;
        mainWindow.Top = mainWindow.WindowPosition.Y;
    }

コード ビハインドでバインディングを作成する必要があることがわかりました。MainWindow次の行をコンストラクターに追加しました。

        SetBinding(WindowPositionProperty, new Binding("SelectedPos"));

最後に、メイン ウィンドウのバインディングLeftを削除しました。Top

于 2012-02-16T23:02:12.093 に答える