하아찡

[C#/WPF] Upbit프로젝트 CoinList 본문

C#/코인프로그램 - 코드

[C#/WPF] Upbit프로젝트 CoinList

하아찡 2023. 11. 29. 15:50

코인 목록 불러옴.

 

 

 

CoinList.xaml

<UserControl x:Class="Upbit.Views.CoinList"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:prism="http://prismlibrary.com/"             
             xmlns:conv="clr-namespace:Upbit.Converter"
             xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
             prism:ViewModelLocator.AutoWireViewModel="True">
    <UserControl.Resources>
        <conv:IsBoolToVisblityConverter x:Key="IsBoolToVisblityConverter"/>
    </UserControl.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30" />
            <RowDefinition Height="1*" />
        </Grid.RowDefinitions>

        <Grid Grid.Row="0">
            <ComboBox x:Name="CbSelectMarket" SelectedIndex="0">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="SelectionChanged">
                        <i:InvokeCommandAction Command="{Binding SelectCurrencyCommand}" CommandParameter="{Binding ElementName=CbSelectMarket}" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
                <ComboBoxItem>ALL</ComboBoxItem>
                <ComboBoxItem>KRW</ComboBoxItem>
                <ComboBoxItem>BTC</ComboBoxItem>
                <ComboBoxItem>USDT</ComboBoxItem>
            </ComboBox>
        </Grid>

        <Grid Grid.Row="1">
            <ListView x:Name="LvMarket" ItemsSource="{Binding ViewMarket , UpdateSourceTrigger=PropertyChanged }"  ScrollViewer.HorizontalScrollBarVisibility="Hidden">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="MouseDoubleClick">
                        <i:InvokeCommandAction Command="{Binding CommandSendCoin}" CommandParameter="{Binding ElementName=LvMarket, Path=SelectedItem}" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
                <ListView.View >
                    <GridView>
                        <GridViewColumn Header="{Binding Lang.LCoinName}" Width="100">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding Print_name}"/>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>

                        </GridViewColumn>
                        <GridViewColumn Header="{Binding Lang.LRate}" DisplayMemberBinding="{Binding Rate,StringFormat={}{0}%}" Width="100"/>
                        <GridViewColumn Header="{Binding Lang.LMarket}" DisplayMemberBinding="{Binding Market}" Width="80"/>
                        <!--GridViewColumn Header="주의종목" DisplayMemberBinding="{Binding Market_warning}" Width="100"/-->
                    </GridView>
                </ListView.View>
            </ListView>
        </Grid>
    </Grid>
</UserControl>

 

 

CoinListViewModel.cs

using Language;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Threading;
using Upbit.Event;
using Upbit.Functions;
using Upbit.Functions.Interface;
using Upbit.UpbitFunctions;
using Upbit.Views;
using System.Resources;

namespace Upbit.ViewModels
{

    public static class DispatcherService
    {
        public static void Invoke(Action action)
        {
            try
            {
                Dispatcher dispatchObject = Application.Current != null ? Application.Current.Dispatcher : null;
                if (dispatchObject == null || dispatchObject.CheckAccess())
                    action();
                else
                    dispatchObject.Invoke(action);
            }
            catch (Exception ex)
            {

            }
            
        }
    }
    public class CoinListViewModel : BindableBase,IWebSocketTicker, ILanguage
    {

        private PublicFunctions Upbitpf = new PublicFunctions();
        
        private WebSocketTicker wsc;

        #region Models
        private string selectmartket;
        public string SelectMarket
        {
            get { return selectmartket; }
            set { SetProperty(ref selectmartket, value); }
        }

        private CollectionViewSource viewmarket { get; set; }

        public ICollectionView ViewMarket
        {
            get { return viewmarket.View;}
        }

        private Timer refreshTimer;

        /// <summary>
        /// 모든 마켓 정보들
        /// </summary>
        private List<Structs.MarketCodes> markets;
        public List<Structs.MarketCodes> Markets
        {
            get { return markets; }
            set { SetProperty(ref markets, value); }
        }

        private bool namevisibility;
        public bool NameVisiblity
        {
            get { return namevisibility; }
            set { SetProperty(ref namevisibility, value); }
        }
        #endregion Models

        #region Lang

        private Language.Lang.PublicCoin lang;
        public Language.Lang.PublicCoin Lang
        {
            get { if (lang is null) lang = new Language.Lang.PublicCoin(); return lang; }
            set { SetProperty(ref lang, value); }
        }

        public virtual void SetLanguage()
        {
            Lang.UpdateLang();
            if ("kr" == Language.Language.Lang.LangType)
                NameVisiblity = true;
            else
                NameVisiblity = false;

            UpdatePrintMarket();
        }
        #endregion Lang

        #region Prism
        private IEventAggregator _ea;
        #endregion Prism

        #region Event
        /// <summary>
        /// 코인 선택 이벤트
        /// </summary>
        private DelegateCommand<object> _sendcoin;
        public DelegateCommand<object> CommandSendCoin =>
            _sendcoin ?? (_sendcoin = new DelegateCommand<object>(ExecuteCommandSendCoin));

        void ExecuteCommandSendCoin(object obj)
        {
            if (obj is null) return;
            Structs.MarketCodes marketCodes = (Structs.MarketCodes)obj;

            _ea.GetEvent<MessageCoinNameEvent>().Publish(marketCodes);
           
        }

        private DelegateCommand<object> selectcurrency;
        public DelegateCommand<object> SelectCurrencyCommand =>
            selectcurrency ?? (selectcurrency = new DelegateCommand<object>(ExecuteSelectCurrency));

        void ExecuteSelectCurrency(object obj)
        {
            ComboBoxItem typeItem = (ComboBoxItem)((ComboBox)obj).SelectedItem;
            SelectMarket = typeItem.Content.ToString();

            UpdatePrintMarket();

            //Markets.ForEach(x => x.Print_name = NameVisiblity ? x.Korean_name : x.English_name) ;
            if (SelectMarket == "ALL")
                SelectMarket = "";
            CoinFilter = SelectMarket;

            //if (SelectMarket == "ALL") { Markets.ForEach(x => PrintMarkets.Add(x)); }
            //else if (SelectMarket == "KRW") { KRWMarkets.ForEach(x => PrintMarkets.Add(x)); }
            //else if (SelectMarket == "BTC") { BTCMarkets.ForEach(x => PrintMarkets.Add(x)); }
            //else { USDTMarkets.ForEach(x => PrintMarkets.Add(x)); }
        }
        #endregion Event

        #region Functions
        private void UpdatePrintMarket()
        {
            if(Markets is not null)
            {
                for (int i = 0; i < Markets.Count; i++)
                {
                    Markets[i].Print_name = NameVisiblity ? Markets[i].Korean_name : Markets[i].English_name; 
                }
                OnFilterChange();
            }
            
        }
        /// <summary>
        /// 등락율 갱신 1초마다 변경
        /// </summary>
        private void RefreshTimer()
        {
            //기본 1초
            refreshTimer = new Timer(1000);
            refreshTimer.AutoReset = true;
            refreshTimer.Elapsed += (sender, e) =>
            {
                DispatcherService.Invoke(() =>
                {
                    viewmarket.View.Refresh();
                });
            };

            refreshTimer.Start();
        }
        #endregion Functions

        #region Interface
        public virtual void TradeEvent(Structs.Trade tr)
        {
            throw new NotImplementedException();
        }

        public virtual void OrderEvent(Structs.Orderbook ob)
        {
            throw new NotImplementedException();
        }

        public virtual void TickerEvent(Structs.Ticker tick)
        {
            Structs.Ticker ticker = tick;



            double rate = Math.Round(ticker.cr * 100, 2);
            string c = ticker.c;
            if (c == "FALL")
                rate *= -1.0f;
            int index;


            for (int i = 0; i < Markets.Count; i++)
            {
                if (Markets[i].Market == ticker.cd)
                {
                    Markets[i].Rate = rate;
                    /*
                    DispatcherService.Invoke((System.Action)(() =>
                    {
                        Markets[i] = Change;

                    }));
                    */
                    break;
                }

            }


        }
        #endregion Interface

        #region Filter
        private string coinfilter;
        public string CoinFilter
        {
            get { return coinfilter; }
            set { 
                SetProperty(ref coinfilter, value);
                OnFilterChange();
            }
        }
        private void ApplyFilter(object sender, FilterEventArgs e)
        {
            Structs.MarketCodes mc = (Structs.MarketCodes)e.Item;
            
            if (string.IsNullOrWhiteSpace(this.CoinFilter) || this.CoinFilter.Length == 0)
            {
                e.Accepted = true;
            }
            else
            {
                e.Accepted = mc.Market.Split("-")[0].Contains(CoinFilter);
            }

        }

        private void OnFilterChange()
        {
            if(viewmarket.View is not null)
                viewmarket.View.Refresh();
        }
        #endregion



        public CoinListViewModel(IEventAggregator ea)
        {
            //언어 변경됐을경우 이벤트호출
            Language.Language.LangChangeEvent += (SetLanguage);
            SetLanguage();

            _ea = ea;
            Markets = Task.Run(() => Upbitpf.MarketsAsync()).Result;
            viewmarket = new CollectionViewSource();
            viewmarket.Source = this.Markets;
            viewmarket.Filter += ApplyFilter;

            
            UpdatePrintMarket();
            //Markets.ForEach(x => PrintMarkets.Add(x));
            


            List<string> TickList = new List<string>();
            foreach (var coin in Markets)
            {
                TickList.Add(coin.Market);
            }
            wsc = new WebSocketTicker(TickList);
            WebSocketTicker.TickerEvent += new WebSocketTicker.TickEventHandler(TickerEvent);

            

            RefreshTimer();
        }

        ~CoinListViewModel()
        {
            WebSocketTicker.TickerEvent -= new WebSocketTicker.TickEventHandler(TickerEvent);
        }
    }
}

 

대부분 코드가 불러다 사용하는거라 설명은 생략하겠습니다.

 

UI쪽은 변경예정있습니다.

 

반응형