1

WPFとC#のDataBindingで小さなことをしようとしていますが、DataBindingのチュートリアルを理解できません。私の問題は、C#に文字クラスがあり、X座標とY座標がgetであるということです。と関数を設定します。次に、ウィンドウのキャンバスに画像があり、文字クラスの座標を画像にバインドしようとしています。(画像は1つだけで、最初は作成されませんが、キャラクタークラスのインスタンスは1つだけ作成されます)。私がそれを完全に理解できるように、誰かがそれを説明できることを願っています:/

編集:

XAMLは次のとおりです。

<Window x:Class="ProjectChar.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="800" Width="1000" Background="Gray">
<Viewbox StretchDirection="Both" Stretch="Uniform">
    <Grid>
        <Canvas Name="Canv" Background="White" Visibility="Hidden" MaxHeight="750" MaxWidth="1000">
            <Canvas.LayoutTransform>
                <ScaleTransform ScaleY="-1"/>
            </Canvas.LayoutTransform>
            <Image Name="CharImage"  Source="CharBild.png" Canvas.Left="{Binding iXCoordinate}" Canvas.Top="{Binding iYCoordinate}"/>
        </Canvas>
    </Grid>
</Viewbox>

これがC#パートです:

namespace ProjectChar
{
    public class Char : MainWindow
    {
        public int iXCoordinate { get; set; }
        public int iYCoordinate { get; set; }
    }
}

だから私はどういうわけかそれらを一緒にバインドする必要がありますが、私は正確に方法がわかりません。DataContextを作成する必要があり、UpdateSourceをPropertyChangedに設定する必要があり、Property ChangedのEventHandlerが必要であることは知っていますが、その方法がわかりません。インターネット上のチュートリアルはすべていろいろなことを言っている:/

4

1 に答える 1

3

のX座標とY座標をプロパティにバインドするには、Image次のようにします。

  1. Charからの継承を削除しMainWindowます。
  2. MainWindowDataContextインスタンスを。に設定しますChar
  3. から削除Visibility="Hidden"しますCanvas

例:

public class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new Char { iXCoordinate = 20, iYCoordinate = 50 };
    }
}

iXCoordinateiYCoordinateプロパティを実際に何かに設定していることを確認してください。そうでない場合は、デフォルト値のint0になります。たとえば、画像は左上隅に表示されます。

バインドされた値が変更されたことをビュー(UI)に通知するには、プロパティが設定されるたびにイベントを実装INotifyPropertyChangedして発生させます。PropertyChanged

public class Char : INotifyPropertyChanged
{
    private int _iXCoordinate;

    public int iXCoordinate
    {
        get { return _iXCoordinate; }
        set
        {
            _iXCoordinate = value;
            OnPropertyChanged("iXCoordinate");
        }
    }

    private int _iYCoordinate;

    public int iYCoordinate
    {
        get { return _iYCoordinate; }
        set
        {
            _iYCoordinate = value;
            OnPropertyChanged("iYCoordinate");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

これは、を実装する最も簡単な方法INotifyPropertyChangedです。ただし、インターフェイスを実装する基本クラスを作成し、ViewModelにそれを継承させることをお勧めします。次のようなものを試してください。

public class PropertyChangedBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged<T>(Expression<Func<T>> propertyExpression)
    {
        var handler = PropertyChanged;
        var propertyName = GetPropertyName(propertyExpression);
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }

    private static string GetPropertyName<T>(Expression<Func<T>> propertyExpression)
    {
        var memberExpression = propertyExpression.Body as MemberExpression;
        if (memberExpression == null)
        {
            var unaryExpression = propertyExpression.Body as UnaryExpression;
            if (unaryExpression == null) 
                throw new ArgumentException("Expression must be a MemberExpression.", "propertyExpression");

            memberExpression = unaryExpression.Operand as MemberExpression;
        }

        if (memberExpression == null) 
            throw new ArgumentException("Expression must be a MemberExpression.", "propertyExpression");

        var propertyInfo = memberExpression.Member as PropertyInfo;
        if (propertyInfo == null) 
            throw new ArgumentException("Expression must be a Property.", "propertyExpression");

        return propertyInfo.Name;
    }
}

これには、タイプミスが発生しやすく、リファクタリングに適さない「マジックストリング」を使用する代わりに、ラムダ式を使用しPropertyChangedBaseてイベントを発生させる必要があるという追加の利点もあります。PropertyChanged

    public int iYCoordinate
    {
        get { return _iYCoordinate; }
        set
        {
            _iYCoordinate = value;
            OnPropertyChanged(() => iYCoordinate);
        }
    }

ただし、実際の問題は、ViewBoxをラップすることGridです。

ViewBoxサイズに子供を測定しInfinity、次にそれらを彼らのによって配置しますDesiredSize。これは、子供が好きなサイズになり得ることを意味します。どちらも、彼らが望むサイズを持っていませんGrid、彼らは彼らにサイズを与えるために彼らの親に頼っています。Canvas

問題を解決するには、とを指定WidthHeightて、GridまたはそのCanvas中を指定します。

ところで:あなたはそれを知っています

<Canvas.LayoutTransform>
  <ScaleTransform ScaleY="-1"/>
</Canvas.LayoutTransform>

あなたの洞窟をひっくり返しますよね?

于 2012-11-20T20:06:41.793 に答える