5

このような複数の Texbox を持つビューがあるとします。

<TextBox Text="{Binding myText1, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />

それぞれにすでにいくつかのテキストが含まれています。ユーザーがこのテキストを変更すると、テキストボックスの境界線がオレンジ色に変わり、変更を元に戻すと、デフォルトの色になります。

現時点では、私はこのようにしています

<TextBox Height="23"  Text="{Binding myText1, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" BorderThickness="2">
   <TextBox.Style>
        <Style TargetType="TextBox">
             <Style.Triggers>
                 <DataTrigger Binding="{Binding myDirtyText1, UpdateSourceTrigger=PropertyChanged}" Value="True">
                     <Setter Property="BorderBrush" Value="Orange"/>
                 </DataTrigger>
             </Style.Triggers>
        </Style>
    </TextBox.Style>
</TextBox>

これを行うためのより一般的/簡単な方法はありますか?

編集

私はすでにエラー検証にIDataErrorInfo+を使用しています。System.ComponentModel.DataAnnotationsこの場合も同様の方法があるかもしれませんが、xaml とコードを最小限に抑えるのに役立つものは見つかりませんでした。

編集 2.0

あなたは私の問題を本当に理解していないと思うので、実際にどのように見えるかのより良いサンプルを提供します:

Xaml を表示 (分離コードなし)

<Grid Margin="12">
    <Label Content="Name:" Height="28" HorizontalAlignment="Left" VerticalAlignment="Top" Width="79" />
    <TextBox Height="23" HorizontalAlignment="Left" Margin="102,2,0,0" VerticalAlignment="Top" Width="170" BorderThickness="2"
             Text="{Binding NameD, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}">
        <TextBox.Style>
            <Style TargetType="TextBox">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding dirtyName, UpdateSourceTrigger=PropertyChanged}" Value="True">
                        <Setter Property="BorderBrush" Value="Orange"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBox.Style>
    </TextBox>

    <Label Content="Anzeigetext:" Height="28" HorizontalAlignment="Left" Margin="0,34,0,0" VerticalAlignment="Top" Width="79" />
    <TextBox BorderThickness="2" Height="23" HorizontalAlignment="Left" Margin="102,36,0,0" VerticalAlignment="Top" Width="170" 
             Text="{Binding AnzeigetextD, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}">
        <TextBox.Style>
            <Style TargetType="TextBox">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding dirtyAnzeigetext, UpdateSourceTrigger=PropertyChanged}" Value="True">
                        <Setter Property="BorderBrush" Value="Orange"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBox.Style>
    </TextBox>

    <Label Content="Preis:" Height="28" HorizontalAlignment="Left" Margin="0,68,0,0" VerticalAlignment="Top" Width="79" />
    <TextBox BorderThickness="2" Height="23" HorizontalAlignment="Left" Margin="102,70,0,0" VerticalAlignment="Top" Width="170" 
             Text="{Binding PreisD, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, StringFormat=\{0:c\}}">
        <TextBox.Style>
            <Style TargetType="TextBox">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding dirtyPreis, UpdateSourceTrigger=PropertyChanged}" Value="True">
                        <Setter Property="BorderBrush" Value="Orange"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBox.Style>
    </TextBox>

    <Button Content="Speichern" Height="23" HorizontalAlignment="Left" Margin="102,110,0,0" VerticalAlignment="Top" Width="75" Command="{Binding SaveCommand}"/>
    <Button Content="Abbrechen" Height="23" HorizontalAlignment="Left" Margin="197,110,0,0" VerticalAlignment="Top" Width="75" Command="{Binding CancelCommand}"/>
</Grid>

ビューモデル

public class MenuangebotVM : DetailVM, IContains
{
    #region private Values
    private Menuangebot myOriginal = new Menuangebot();
    private Menuangebot myValue = new Menuangebot();
    #endregion // private Values

    #region Properties

    #region Detail Properties
    public int Id { get { return myOriginal.Id; } }
    public bool? Result { get; private set; }
    public string Beschreibung { get { return "Einrichtung"; } }

    [Required]
    [RegularExpression(@"^[0-9a-zA-ZäöüßÄÖÜß''-'\s]{2,40}$")]
    public string NameD
    {
        get { return myValue.Name; }
        set
        {
            myValue.Name = value;
            RaisePropertyChanged(() => Reg(() => NameD));
            RaisePropertyChanged(() => Reg(() => dirtyName));
        }
    }
    public bool dirtyName
    {
        get { return (!isNew && myValue.Name != myOriginal.Name) ? true : false; }
    }

    [Required]
    [RegularExpression(@"^[0-9a-zA-ZäöüßÄÖÜß''-'\s]{2,25}$")]
    public string AnzeigetextD
    {
        get { return myValue.Anzeigetext; }
        set
        {
            myValue.Anzeigetext = value;
            RaisePropertyChanged(() => Reg(() => AnzeigetextD));
            RaisePropertyChanged(() => Reg(() => dirtyAnzeigetext));
        }
    }
    public bool dirtyAnzeigetext
    {
        get { return (!isNew && myValue.Anzeigetext != myOriginal.Anzeigetext) ? true : false; }
    }

    [Required]
    public decimal PreisD
    {
        get { return myValue.Preis; }
        set
        {
            myValue.Preis = value;
            RaisePropertyChanged(() => Reg(() => PreisD));
            RaisePropertyChanged(() => Reg(() => dirtyPreis));
        }
    }
    public bool dirtyPreis
    {
        get
        {
            var value = myValue.Preis;
            var Original = myOriginal.Preis;

            return (!isNew && value != Original) ? true : false;
        }
    }

    #endregion //Detail Properties
    #endregion //Properties

// more code

}

私が期待するものは次のようなものでなければなりません

意見

<Grid Margin="12">
    <Label Content="Name:" Height="28" HorizontalAlignment="Left" VerticalAlignment="Top" Width="79" />
    <TextBox Height="23" HorizontalAlignment="Left" Margin="102,2,0,0" VerticalAlignment="Top" Width="170" BorderThickness="2"
             Text="{Binding NameD, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, EditesOnDataChanges=true}">

    </TextBox>

    <Label Content="Anzeigetext:" Height="28" HorizontalAlignment="Left" Margin="0,34,0,0" VerticalAlignment="Top" Width="79" />
    <TextBox BorderThickness="2" Height="23" HorizontalAlignment="Left" Margin="102,36,0,0" VerticalAlignment="Top" Width="170" 
             Text="{Binding AnzeigetextD, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, EditesOnDataChanges=true}">
    </TextBox>

    <Label Content="Preis:" Height="28" HorizontalAlignment="Left" Margin="0,68,0,0" VerticalAlignment="Top" Width="79" />
    <TextBox BorderThickness="2" Height="23" HorizontalAlignment="Left" Margin="102,70,0,0" VerticalAlignment="Top" Width="170" 
             Text="{Binding PreisD, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, StringFormat=\{0:c\, EditesOnDataChanges=true}}">
    </TextBox>

    <Button Content="Speichern" Height="23" HorizontalAlignment="Left" Margin="102,110,0,0" VerticalAlignment="Top" Width="75" Command="{Binding SaveCommand}"/>
    <Button Content="Abbrechen" Height="23" HorizontalAlignment="Left" Margin="197,110,0,0" VerticalAlignment="Top" Width="75" Command="{Binding CancelCommand}"/>
</Grid>

ビューモデル

public class MenuangebotVM : DetailVM, IContains
{
    #region private Values
    private Menuangebot myOriginal = new Menuangebot();
    private Menuangebot myValue = new Menuangebot();
    #endregion // private Values

    #region Properties

    #region Detail Properties
    public int Id { get { return myOriginal.Id; } }
    public bool? Result { get; private set; }
    public string Beschreibung { get { return "Einrichtung"; } }

    [Required]
    [RegularExpression(@"^[0-9a-zA-ZäöüßÄÖÜß''-'\s]{2,40}$")]
    [Default(myOriginal.Name)] //<-- added
    public string NameD
    {
        get { return myValue.Name; }
        set
        {
            myValue.Name = value;
            RaisePropertyChanged(() => Reg(() => NameD));
        }
    }

    [Required]
    [RegularExpression(@"^[0-9a-zA-ZäöüßÄÖÜß''-'\s]{2,25}$")]
    [Default(myOriginal.Anzeigetext)] //<-- added
    public string AnzeigetextD
    {
        get { return myValue.Anzeigetext; }
        set
        {
            myValue.Anzeigetext = value;
            RaisePropertyChanged(() => Reg(() => AnzeigetextD));
        }
    }

    [Required]
    [Default(myOriginal.Preis)] //<-- added
    public decimal PreisD
    {
        get { return myValue.Preis; }
        set
        {
            myValue.Preis = value;
            RaisePropertyChanged(() => Reg(() => PreisD));
        }
    }    
    #endregion //Detail Properties
    #endregion //Properties

// more code

}
4

4 に答える 4

0

偶然にも、私はあなたとほとんど同じ問題を抱えていました、そして私はそれをで包むことによってそれを解決しTextBoxましたBorder。さらに、これにより、Windows8マシンでBorderBrushの色を変更できないという問題も解決されました。

したがって、このアプローチをお勧めします。コードは非常に単純で、textBoxをに追加しBorderて境界線のBorderBrushプロパティを変更するだけです。

于 2013-03-20T11:46:56.973 に答える
0

そのために Attached 動作を使用できます

public static class TextChangedAttachedBehavior
{
    public static bool GetChanged(DependencyObject obj)
    {
        return (bool)obj.GetValue(ChangedProperty);
    }

    public static void SetChanged(DependencyObject obj, string value)
    {
        obj.SetValue(ChangedProperty, value);
    }

    public static readonly DependencyProperty ChangedProperty =
        DependencyProperty.RegisterAttached("Changed", typeof(bool),
        typeof(TextChangedAttachedBehavior), new PropertyMetadata(false, HookupBehavior));

    private static void HookupBehavior(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var textBox = d as TextBox;
        if (textBox == null) 
            return;
        textBox.TextChanged += TextBoxOnTextChanged;
    }

    private static void TextBoxOnTextChanged(object sender, TextChangedEventArgs args)
    {
        var textBox = sender as TextBox;
        if (textBox == null)
            return;
        textBox.BorderBrush = new SolidColorBrush(Colors.Orange);
    }
}

そして、xamlよりも

<TextBox Text="{Binding myText1, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" TextChangedAttachedBehavior.Changed = "True" />
于 2013-07-23T10:05:57.480 に答える
0
public class ViewModel:INotifyPropertyChanged
    {
        private string initialText;
        public ViewModel()
        {
            Text = "ABCD";
            initialText = Text;
            DefaultBorder = true;
        }
        private string text;
        public string Text
        {
            get { return text; }
            set { text = value;
            if (value == initialText)
                DefaultBorder = true;
            else
                DefaultBorder = false;
                Notify("Text"); }
        }

        private bool defaultBorder;
        public bool DefaultBorder
        {
            get { return defaultBorder; }
            set { defaultBorder = value; Notify("DefaultBorder"); }
        }

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

        public event PropertyChangedEventHandler PropertyChanged;
    }

public class MyConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value != null && value is bool && !(bool)value)
                return new SolidColorBrush(Colors.Orange);
            else
                return new SolidColorBrush(Colors.Navy); //Or default whatever you want

        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    <Window.Resources>
    <local:MyConverter x:Key="MyConverter"/>
</Window.Resources>
<Grid>
    <TextBox BorderThickness="4" BorderBrush="{Binding DefaultBorder, Converter={StaticResource MyConverter}}" Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>

ここでは、ViewModel に TextBox にバインドされたプロパティ Text があり、最初は Text の初期値を保持しています。そして、ユーザーが Text プロパティのセッターでそれを比較し、それに応じて Bool プロパティを設定すると、この bool プロパティはコンバーターを使用してバインドする色を指定します。マイナーな問題は無視してください。

于 2013-03-20T11:43:19.967 に答える
0

おそらく、これをカスタム コントロール/UserControl にして、IsDirtyDependencyProperty と IsDirtyColorDependencyProperty (または添付の依存関係プロパティ) を追加できます。そうすれば、すべてのテキストボックスをこれに置き換えることができ、コードを何度も繰り返す必要がなくなります。

于 2013-03-20T11:43:26.197 に答える