Привязка не обновляет текст после перемены мест элементов массива
Использую паттерн MVVM. Есть модель - Todo.
public class Todo : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName]string prop = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}
public TodoUI ui;
public bool ignore_id_changes;
public string prev_id;
private string id;
public string ID
{
get { return id; }
set {
byte b = 0;
if (!byte.TryParse(value, out b)) { return; };
if (ui.Todos.Count < b) { return; }
id = value;
OnPropertyChanged("ID");
if (!ignore_id_changes) ui.Replace(this);
}
}
}
ЕстьViewModel - TodoUI
public class TodoUI : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName]string prop = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}
public ObservableCollection<Todo> Todos
{
get;
set;
}
public TodoUI()
{
Todos = new ObservableCollection<Todo>();
}
public void Replace(Todo active_todo)
{
Todo was_a;
Todo was_p;
Todo a = null;
Todo p = null;
byte a_id = 0;
byte p_id = 0;
for (byte i = 0; i < Todos.Count; i++)
{
if (active_todo.ID == Todos[i].ID && Todos[i] != active_todo)
{
p = Todos[i];
p_id = i;
}
}
for (byte i = 0; i < Todos.Count; i++)
{
if (Todos[i] == active_todo)
{
a = Todos[i];
a_id = i;
if (p == null) { return; }
a.ignore_id_changes = true;
p.ignore_id_changes = true;
////////////////////
Todos[p_id].ID = a.prev_id;
Todos[p_id].prev_id = p.ID;
Todos[a_id].prev_id = a.ID;
////////////////////
Todos[a_id] = p;
Todos[p_id] = a;
a.ignore_id_changes = false;
p.ignore_id_changes = false;
}
}
//End
}
}
Ну и View - AllTodosPage
<Page x:Class="TodoList.AllTodosPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:TodoList"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="AllTodosPage" KeyDown="Page_KeyDown">
<Grid Background="{StaticResource back}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="33"/>
</Grid.ColumnDefinitions>
<Button Content="Add new todo" FontWeight="Medium" FontSize="22" Foreground="White" HorizontalAlignment="Left" Style="{StaticResource txt_btn}" Click="OnAddBtnClick"/>
<Button Grid.Column="1" Content="←" FontWeight="Medium" FontSize="22" Foreground="White" Style="{StaticResource txt_btn}" HorizontalAlignment="Center" Click="OnReturnBtnClick" />
</Grid>
<!--List-->
<ListBox Background="{StaticResource back}" HorizontalContentAlignment="Stretch" BorderThickness="0" ItemsSource="{Binding Todos}" Grid.Row="1" Name="data_el">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Foreground" Value="White" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Name="Border" Background="{StaticResource unselected}" Margin="0 2 0 0" SnapsToDevicePixels="true">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource select}"/>
</Trigger>
<DataTrigger Binding="{Binding Completed}" Value="False">
<Setter Property="Foreground" Value="Gray" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.Resources>
<Style TargetType="TextBox">
<Setter Property="FontWeight" Value="Regular" />
<Setter Property="FontSize" Value="15" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="SelectionBrush" Value="{StaticResource back}" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="HorizontalAlignment" Value="Left" />
</Style>
<Style TargetType="Button">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="White" />
<Setter Property="FontWeight" Value="Regular" />
<Setter Property="FontSize" Value="15" />
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="25"/>
<!--ID-->
<ColumnDefinition Width="*"/>
<!--Text-->
<ColumnDefinition Width="25"/>
<!--Splitter-->
<ColumnDefinition Width="0.3*"/>
<!--Time-->
<ColumnDefinition Width="25"/>
<!--Done-->
<ColumnDefinition Width="25"/>
<!--Edit-->
<ColumnDefinition Width="25"/>
<!--Remove-->
</Grid.ColumnDefinitions>
<TextBox Text="{Binding ID, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Text="{Binding Text, Mode=TwoWay}" HorizontalAlignment="Left" MinWidth="45" Grid.Column="1" Name="text_tb"/>
<TextBox Text="{Binding Time, Mode=TwoWay}" HorizontalAlignment="Left" MinWidth="20" MaxWidth="40" Grid.Column="3" Name="time_tb" />
<Button Grid.Column="4" Content="✓" Click="OnCompleteBtnClick" />
<Button Grid.Column="5" Content="..." Click="OnDetailsBtnClick"/>
<Button Grid.Column="6" Content="X" Click="OnDelBtnClick" />
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Completed}" Value="True">
<Setter TargetName="time_tb" Property="TextDecorations" Value="Strikethrough"/>
<Setter TargetName="text_tb" Property="TextDecorations" Value="Strikethrough"/>
<Setter TargetName="time_tb" Property="Foreground" Value="Black" />
<Setter TargetName="text_tb" Property="Foreground" Value="Black" />
</DataTrigger>
<DataTrigger Binding="{Binding Completed}" Value="False">
<Setter TargetName="time_tb" Property="TextDecorations" Value="None" />
<Setter TargetName="text_tb" Property="TextDecorations" Value="None" />
<Setter TargetName="time_tb" Property="Foreground" Value="White" />
<Setter TargetName="text_tb" Property="Foreground" Value="White" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<!--End list-->
</Grid>
Проблема в том, что если просто менять свойство ID, то все хорошо. Но как только начать менять местами элементы массива, то у P перестает отображаться изменение ID (Сам ID меняется).
Как исправить отображение изменений ID?
Ответы (1 шт):
Автор решения: original_name
→ Ссылка
Как оказалось, если вынести код с изменением id и перемещением Todo в массиве из аксессора в событие опускания клавиши, то все работает прекрасно. Еще выяснилось, что все и отрабатывало, вот только визуал почему-то частично сбрасывался. Решил проблему с отображением id удалением и вставкой тех же Todo в массив.
Todos.Remove(a);
Todos.Remove(p);
//проверка на возможность вставки опущена
Todos.Insert(a);
Todos.Insert(p);
![Без Todos[a_id] = p; Todos[p_id] = a;](https://i.stack.imgur.com/93m87.png)
