我有三个不同的 ObservableCollections
绑定到我的视图中。我把它们传递给函数,它们在循环中被编辑,我想在我的视图中显示这些集合的每一个变化。
所有的绑定都能正常工作,我唯一的问题是只有在函数结束时UI才会更新,所以我只能在更改后才能显示这些集合。
这是我的函数,它是解决TSP问题的NearestNeighbour算法的实现,我想在我的视图中打印解决它的每一步。
public int TSP(ObservableCollection<City> VisitedCities, ObservableCollection<Edge> CurrentEdges, ObservableCollection<Edge> FinalEdges)
{
int bestDistance = 0;
City currentCity = cities.First();
cities.RemoveAt(0);
VisitedCities.Add(new City(currentCity.X, currentCity.Y, currentCity.Number));
int minWeight = int.MaxValue;
City tmp = currentCity;
do
{
foreach(City city in cities)
{
if (minWeight > neighbourMatrix[currentCity.Number, city.Number] && neighbourMatrix[currentCity.Number,city.Number] !=0)
{
minWeight = neighbourMatrix[currentCity.Number, city.Number];
tmp = city;
}
CurrentEdges.Add(new Edge(currentCity.X, currentCity.Y, city.X, city.Y, neighbourMatrix[currentCity.Number, city.Number]));
}
FinalEdges.Add(new Edge(currentCity.X, currentCity.Y, tmp.X, tmp.Y, neighbourMatrix[currentCity.Number, tmp.Number]));
bestDistance += neighbourMatrix[currentCity.Number, tmp.Number];
CurrentEdges.Clear();
VisitedCities.Add(new City(tmp.X, tmp.Y, tmp.Number));
currentCity = new City(tmp.X, tmp.Y, tmp.Number);
cities.Remove(tmp);
minWeight = int.MaxValue;
} while (cities.Any());
FinalEdges.Add(new Edge(VisitedCities.Last().X, VisitedCities.Last().Y, VisitedCities.First().X, VisitedCities.First().Y, neighbourMatrix[VisitedCities.Last().Number, VisitedCities.First().Number]));
return bestDistance;
}
我有一个想法,使用 ComponentDispatcher
当我更换了我的 do{...}while()
但正如你所看到的,我还需要另一个循环来进行计算,因此我只能打印当前的顶点,以及每一步通往下一个顶点的路径。因此,我只能打印当前顶点,以及每一步通往下一个顶点的路径。我想同时打印当前检查过的每一条边。foreach(..)
循环。
谁能帮我解决这个问题?我还想实现A*算法和模拟退火,所以解决方案不应该只限于使用该函数。
Shefff,
使用BackgroundWorker和Dispatcher刷新ObservableCollection绑定的示例代码。
DataGrid XAML
<DataGrid HorizontalAlignment="Left"
Height="203"
Margin="175,126,0,0"
DataContext="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
ItemsSource="{ Binding Path=Persons }"
VerticalAlignment="Top"
Width="378" >
<DataGrid.Resources>
<Style TargetType="DataGridRow">
<EventSetter Event="MouseDoubleClick" Handler="Row_DoubleClick"/>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
<DataGridTextColumn Header="LastName" Binding="{Binding LastName}"/>
<DataGridTextColumn Header="Age" Binding="{Binding Age}"/>
</DataGrid.Columns>
</DataGrid>
代码背后
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Row_DoubleClick(object sender, MouseButtonEventArgs e)
{
var dbClickedRow = (DataGridRow)sender;
MessageBox.Show(((Person)dbClickedRow.DataContext).Name);
}
public ObservableCollection<Person> Persons { get; set; } = new ObservableCollection<Person>();
private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < 500; i++)
{
Thread.Sleep(1000);
Dispatcher.Invoke(() => Persons.Add(new Person { Age = i, Name = "SomeName" + i, LastName = "SomeLastName" + i }));
}
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Persons.Add(new Person { Name = "Gustavo", LastName = "Oliveira", Age = 35 });
Persons.Add(new Person { Name = "Another", LastName = "Person", Age = 23 });
Persons.Add(new Person { Name = "Neymar", LastName = "Junior", Age = 28 });
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += Worker_DoWork;
worker.RunWorkerAsync();
}
}
public class Person
{
public string Name { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}