0

EDITED:コメントが示唆しているように、MVVM パターンを実装する必要があります。まさにそれを実行しました。ただし、同じ問題が引き続き発生します。したがって、それに応じて質問を変更しました。

監視可能なコレクション (MyNotes クラス内) にバインドされた 2 つの列を含むデータグリッドがあります。1 つの列にはコンボボックスが含まれ、もう 1 つの列にはテキストボックスが含まれます。このコレクションには、列挙型変数 (コンボ ボックスで表示) と文字列 (テキスト ボックスで表示) を含む Note オブジェクトへの参照が格納されます。SelectedItems (したがって SelectedItem) を除いて、すべて正常に動作します。プログラムをビルドして実行すると、(追加/削除ボタンを使用して) データグリッドに新しい行を追加できますが、(データグリッドのテキストボックスまたはコンボボックスに入力して) 編集を試みると、データグリッドの selectedItems と selectedItem が失敗します。これは、追加/削除ボタンを使用して確認できます。選択した行は削除されず、選択した行の上に新しい行は追加されません。これは、SelectedNote プロパティがバインドを失うという症状の結果です (なぜこれが起こるのかわかりません。再バインドをハックしようとすると、再バインドが失敗しますか?)。別の症状は、データグリッドが実際に選択されているものとして表示されているものを反映していない、選択された項目のプロパティに関連しています (デバッグモードで表示した場合)。

この問題はデータグリッドの問題に関連していると確信しており、私の場合は使用できません。

これが新しい XAML です (そのデータ コンテキスト、ビューモデルは XAML で設定され、ParaTypes と headerText は両方とも XAML 静的リソースです)。

<DataGrid x:Name                  ="dgdNoteLimits"
              ItemsSource             ="{Binding ParagraphCollection}"
              SelectedItem            ="{Binding Path=SelectedNote, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
              AllowDrop               ="True"
              HeadersVisibility       ="Column"
              AutoGenerateColumns     ="False"
              CanUserAddRows          ="False"
              CanUserReorderColumns   ="False"
              CanUserSortColumns      ="False"
              BorderThickness         ="0"
              VerticalGridLinesBrush  ="DarkGray"
              HorizontalGridLinesBrush="DarkGray"
              SelectionMode           ="Extended"
              SelectionUnit           ="FullRow"
              ColumnHeaderStyle       ="{StaticResource headerText}">
        <DataGrid.ItemContainerStyle>
            <Style>
                <Style.Resources>
                    <!-- SelectedItem's background color when focused -->
                    <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
                                         Color="Blue"/>
                    <!-- SelectedItem's background color when NOT focused -->
                    <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}"
                                         Color="Blue" />
                </Style.Resources>
            </Style>
        </DataGrid.ItemContainerStyle>
        <DataGrid.Columns>
            <DataGridComboBoxColumn Header              = "Note Type"
                                    ItemsSource         = "{Binding Source={StaticResource ParaTypes}}"
                                    SelectedValueBinding= "{Binding Path=NoteType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                    TextBinding         = "{Binding Path=NoteType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                    MinWidth            = "115"
                                    Width               = "Auto">
            </DataGridComboBoxColumn>
            <DataGridTextColumn Header ="Description"
                                Binding="{Binding Path=NoteText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                Width  ="*">
                <DataGridTextColumn.ElementStyle>
                    <Style TargetType="TextBlock">
                        <Setter Property="TextWrapping"
                                Value   ="Wrap"/>
                    </Style>
                </DataGridTextColumn.ElementStyle>
                <DataGridTextColumn.EditingElementStyle>
                    <Style TargetType="TextBox">
                        <Setter Property="SpellCheck.IsEnabled"
                                Value   ="true" />
                        <Setter Property="TextWrapping"
                                Value   ="Wrap"/>
                    </Style>
                </DataGridTextColumn.EditingElementStyle>
            </DataGridTextColumn>
        </DataGrid.Columns>
    </DataGrid>
    <StackPanel Grid.Row="1"
                Margin="0, 0, 0, 16"
                Orientation="Horizontal"
                HorizontalAlignment="Right">
        <Button Content="Add"
                Width="72"
                Margin="16,8,8,8"
                Command="{Binding AddClickCommand}"/>
        <Button Content="Remove"
                Width="72"
                Margin="16,8,8,8"
                Command="{Binding RemoveClickCommand}"/>
    </StackPanel>

ビューモデルは次のとおりです。

class MainWindowViewModel : INotifyPropertyChanged
{
    MyNotes NotesCollection;
    private bool canExecute;
    private ICommand clickCommand;

    public MainWindowViewModel()
    {
        this.NotesCollection = new MyNotes();
        this.ParagraphCollection = this.NotesCollection.Notes;
        this.canExecute = true;
    }

    private ObservableCollection<Note> paragraphCollection;
    public ObservableCollection<Note> ParagraphCollection
    {
        get { return this.paragraphCollection; }
        set
        {
            this.paragraphCollection = value;
            RaisePropertyChanged(() => this.ParagraphCollection);
        }
    }

    private Note selectedNote;
    public Note SelectedNote
    {
        get { return this.selectedNote; }
        set
        {
            if (this.selectedNote == value)
                return;

            this.selectedNote = value;
            RaisePropertyChanged(() => this.SelectedNote);
        }
    }

    public ICommand AddClickCommand
    {
        get
        {
            return this.clickCommand ?? (new ClickCommand(() => AddButtonHandler(), canExecute));
        }
    }
    public void AddButtonHandler()
    {
        int noteIndex = 0;
        Note aNote;

        // what to do if a note is either selected or unselected...
        if (this.SelectedNote != null)
        {
            // if a row is selected then add row above it.
            if (this.SelectedNote.NoteIndex != null)
                noteIndex = (int)this.SelectedNote.NoteIndex;
            else
                noteIndex = 0;

            //create note and insert it into collection.
            aNote = new Note(noteIndex);
            ParagraphCollection.Insert(noteIndex, aNote);

            // Note index gives sequential order of collection
            // (this allows two row entries to have same NoteType
            // and NoteText values but still note equate).
            int counter = noteIndex;
            // reset collection index so they are sequential
            for (int i = noteIndex; i < this.NotesCollection.Notes.Count; i++)
            {
                this.NotesCollection.Notes[i].NoteIndex = counter++;
            }
        }
        else
        {
            //if a row is not selected add it to the bottom.
            aNote = new Note(this.NotesCollection.Count);
            this.ParagraphCollection.Add(aNote);
        }
    }

    public ICommand RemoveClickCommand
    {
        get
        {
            return this.clickCommand ?? (new ClickCommand(() => RemoveButtonHandler(), canExecute));
        }
    }
    public void RemoveButtonHandler()
    {
        //delete selected note.
        this.ParagraphCollection.Remove(selectedNote);
    }

    //boiler plate INotifyPropertyChanged implementation!
    public event PropertyChangedEventHandler PropertyChanged;
    protected void RaisePropertyChanged<T>(Expression<System.Func<T>> propertyExpression)
    {
        var memberExpr = propertyExpression.Body as MemberExpression;
        if (memberExpr == null)
            throw new ArgumentException("propertyExpression should represent access to a member");
        string memberName = memberExpr.Member.Name;
        RaisePropertyChanged(memberName);
    }
    protected virtual void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

そしてモデル:

class MyNotes
{
    public ObservableCollection<Note> Notes;

    public MyNotes()
    {
        this.Notes = new ObservableCollection<Note>();
    }
}

public enum NoteTypes
{
    Header, Limitation, Warning, Caution, Note
}

public class Note
{
    public int?      NoteIndex { get; set; }
    public NoteTypes NoteType  { get; set; }
    public string    NoteText  { get; set; }

    public Note()
    {
        this.NoteIndex = null;
        this.NoteType = NoteTypes.Note;
        this.NoteText = "";
    }
    public Note(int? noteIndex): this()
    {
        this.NoteIndex = noteIndex;
    }

    public override string ToString()
    {
        return this.NoteType + ": " + this.NoteText;
    }
    public override bool Equals(object obj)
    {
        Note other = obj as Note;

        if (other == null)
            return false;
        if (this.NoteIndex != other.NoteIndex)
            return false;
        if (this.NoteType != other.NoteType)
            return false;
        if (this.NoteText != other.NoteText)
            return false;

        return true;
    }
    public override int GetHashCode()
    {
        int hash = 17;

        hash = hash * 23 + this.NoteIndex.GetHashCode();
        hash = hash * 23 + this.NoteType.GetHashCode();
        hash = hash * 23 + this.NoteText.GetHashCode();

        return hash;
    }
}

既存のコメントは大歓迎です (私は多くのことを学び、MVVM の価値を理解しています)。彼らが問題を解決していないのは残念です。でもありがとう。

したがって、この問題を解決する方法を誰かが知っていれば、それは大歓迎です。

4

0 に答える 0