none
Не обновляется ListView RRS feed

  • Общие обсуждения

  • Имеется: 

    • MainWindow(view)
    • MainViewModel
    • Model 
    • Класс дающий новые значения по подписке на event

    Как обновить коллекцию с помощью event обновляющего класса? Метод ListView(подписавшийся),при вызове события работает ровно до прохода циклом принятой коллекции, дальше студия глохнет. Может кто-нибудь в курсе почему так происходит и как решить проблему?

    Я хотел чтобы в фоне обновлялись значения коллекции при нажатии на кнопку Run и прекращали на кнопку Stop.

     
    <Window x:Class="wpfMVtest.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:wpfMVtest"
            mc:Ignorable="d"
            Title="MainWindow" Height="440.191" Width="340.191">
        <Grid>
            <Button Content="add" HorizontalAlignment="Left" Margin="30,336,0,0" VerticalAlignment="Top" Width="75" Command="{Binding Add}"/>
            <Button Content="delete half values" HorizontalAlignment="Left" Margin="138,336,0,0" VerticalAlignment="Top" Width="75" Command="{Binding RemoveHalfValues}"/>
            <ListView HorizontalAlignment="Left" Height="192" Margin="41,27,0,0" VerticalAlignment="Top" Width="151" ItemsSource="{Binding Values}">
                <ListView.View>
                    <GridView>
                        <GridViewColumn Header="Number" DisplayMemberBinding="{ Binding Value}" Width="100"/>
                    </GridView>
                </ListView.View>
            </ListView>
            <Button Content="Update All Values" HorizontalAlignment="Left" Margin="126,267,0,0" VerticalAlignment="Top" Width="176" Height="24" Command="{Binding Update}" />
            <Button Content="Run updater" HorizontalAlignment="Left" Margin="223,27,0,0" VerticalAlignment="Top" Width="99" Height="47" Command="{Binding RunUpdater}" />
            <Button Content="Stop updater" HorizontalAlignment="Left" Margin="223,79,0,0" VerticalAlignment="Top" Width="99" Height="47" Command="{Binding StopUpdater}" />
    
        </Grid>
    </Window>
    
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                DataContext = new MainViewModel();
            }
        }



        class MainViewModel
        {
            readonly ObservableCollection<NumberViewModel> values = new ObservableCollection<NumberViewModel>();
    
            MyCommandContainer<RelayCommand> commands;
            UpdateValuesService service;
            public ObservableCollection<NumberViewModel> Values => values;
            Random rand = new Random();
            public MainViewModel()
            {
                commands = new MyCommandContainer<RelayCommand>();
                commands.AddCommand(nameof(Add), new RelayCommand((obj) =>
                {
                 
                    AddMore(rand.NextDouble() * 100 - 1, rand.NextDouble() * 100 - 1, rand.NextDouble() * 100 - 1, rand.NextDouble() * 100 - 1);
    
                }));
                commands.AddCommand(nameof(RemoveHalfValues), new RelayCommand((obj) =>
                {
                      var x = values.Where(v => values.IndexOf(v) % 2 == 0);
                      x.ToList().ForEach(v => values.Remove(v));
                }));
                commands.AddCommand(nameof(Replace), new RelayCommand((obj) =>
                {
                   
                    for (int i = 0; i < values.Count; ++i)
                    {
                        values[i] = new NumberViewModel(rand.NextDouble() * 100 - 1);
                    }
                }));
                commands.AddCommand(nameof(Update), new RelayCommand((obj) =>
                {
                    var rand = new Random();
                    for (int i = 0; i < values.Count; ++i)
                    {
                        values[i].Value = rand.NextDouble() * 100 - 1;
                    }
                }));
    
                commands.AddCommand(nameof(RunUpdater), new RelayCommand((obj) =>
                {
                    service.Run();
                }));
    
                commands.AddCommand(nameof(StopUpdater), new RelayCommand((obj) =>
                {
                    service.Stop();
                }));
    
                service = new UpdateValuesService();
                service.OnUpdate += UpdateValues;
            }
    
            private void UpdateValues(List<double> obj)
            {
                Values.Clear();
                obj.ForEach((x)=> MessageBox.Show(x.ToString()));
            }
    
           
            public ICommand Add
            {
                get
                {
                    var command = commands.GetCommand(nameof(Add));
                    return command;
                }
            }
    
         
            public ICommand RemoveHalfValues
            {
                get => commands.GetCommand(nameof(RemoveHalfValues));
            }
    
            
           public ICommand Replace
           {
                get =>commands.GetCommand(nameof(Replace));
           }
    
            public ICommand Update
            {
                get => commands.GetCommand(nameof(Update));
            }
    
            public ICommand RunUpdater
            {
                get => commands.GetCommand(nameof(RunUpdater));
            }
    
            public ICommand StopUpdater
            {
                get => commands.GetCommand(nameof(StopUpdater));
            }
            void AddMore(params double[]args)
            {
                args.ToList().ForEach(a => Values.Add(new NumberViewModel( a)));
            }
    
        }
    
    
    
    


        class NumberViewModel:INotifyPropertyChanged
        {
            readonly NumberModel _value;
    
            public NumberViewModel(double _n)
            {
                _value = new NumberModel();
                _value.Number = _n;
            }
    
            public double Value { get => _value.Number;
                set
                {
                    _value.Number = value;
    
                    OnChanged(nameof(Value));
                }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            void OnChanged(string name)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
            }
        }

        class NumberModel
        {
            double number;
            public double Number
            {
                get => number;
                set => number = value;
            }
    
        }
        class UpdateValuesService:BaseService<double>
        {
    
            private Random random = new Random();
            protected override List<double> Update()
            {
                
                List<double> vs = new List<double>();
                for(int i=0; i < 10; ++i)
                {
                    vs.Add(random.NextDouble()*100-1);
                }
                return vs;
            }
        }
    
    
        class BaseService<T> : IUpdatableEvent<List<T>>, IRunable ,IWaitable
        {
            private CancellationTokenSource tokenSource = new CancellationTokenSource();
            public TimeSpan Timeout { get; private set; }
    
            public bool IsRun { get; private set; }
    
            public event Action<List<T>> OnUpdate;
    
    
            public void AddAction(Action<List<T>> action)
            {
                OnUpdate += action;
            }
    
            public void ResetAction()
            {
                OnUpdate = null;
                OnUpdate +=(o)=>{ };
            }
    
            public void Run()
            {
                if(IsRun==false)
                Task.Run(async () => 
                {
                    IsRun = true;
                    while (!tokenSource.Token.IsCancellationRequested)
                    {
                        var updVal = Update();
                        OnUpdate(updVal);
                        await  Task.Delay(Timeout);
                    }
                    tokenSource.Token.ThrowIfCancellationRequested();
                },tokenSource.Token); 
            }
    
            public void SetTimeout(TimeSpan time)
            {
                Timeout=time;
            }
    
            public void Stop()
            {
                if (IsRun == true)
                {
                    tokenSource.Cancel();
                    IsRun = false;
                    tokenSource = new CancellationTokenSource();
                }
            }
    
    
            virtual protected List<T> Update()
            {
                throw new NotImplementedException();
            }
        }
    
        interface IRunable
        {
            bool IsRun { get; }
            void Run();
            void Stop();
        }


    17 октября 2019 г. 22:42