From 1a1c8e71fcd14858f595029f089b2d4a00202b32 Mon Sep 17 00:00:00 2001
From: ogi <Administrator@S-OGI-PC>
Date: Fri, 05 Dec 2025 09:24:16 +0900
Subject: [PATCH] プロジェクトファイルを追加。

---
 HotelPms.Client.Blazor/Pages/UseDetail/SaleInput.razor.cs |  648 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 648 insertions(+), 0 deletions(-)

diff --git a/HotelPms.Client.Blazor/Pages/UseDetail/SaleInput.razor.cs b/HotelPms.Client.Blazor/Pages/UseDetail/SaleInput.razor.cs
new file mode 100644
index 0000000..16b9d06
--- /dev/null
+++ b/HotelPms.Client.Blazor/Pages/UseDetail/SaleInput.razor.cs
@@ -0,0 +1,648 @@
+using HotelPms.Client.Blazor.Dialog;
+using HotelPms.Client.Blazor.Models;
+using HotelPms.Client.Blazor.Util;
+using HotelPms.Data.Common;
+using HotelPms.Share.IO;
+using HotelPms.Share.Util;
+using Microsoft.AspNetCore.Components;
+using Microsoft.AspNetCore.Components.Web;
+using MudBlazor;
+using static HotelPms.Client.Blazor.Util.SystemEnum;
+
+namespace HotelPms.Client.Blazor.Pages.UseDetail;
+
+public partial class SaleInput : ComponentBase
+{
+    [Parameter] public ViewModel.UseInput? Data { get; set; }
+    [Parameter] public Action OnRefresh { get; set; }
+
+    private System.Threading.SemaphoreSlim slimlock = new SemaphoreSlim(1, 1);
+
+    private IEnumerable<FeeDtailRow> FeeDetailList = new List<FeeDtailRow>();
+
+    private IEnumerable<SaleChildRow> SaleChildList = new List<SaleChildRow>();
+
+    private SaleInputRow selectedItem1 = null;
+    private List<string> editEvents = new();
+    private string searchString = "";
+    private string RowSpaceStyle = "mt-2 pt-0 mb-0 pb-0";
+    private MudTable<SaleInputRow> _table;
+
+    private bool keyDownPreventDefault = false;
+    private bool keyPressPreventDefault = false;
+    private bool enterPush = false;
+    private bool arrowUpPush = false;
+
+    private EditGridFocusEventArgs m_CurrentFocusData = new EditGridFocusEventArgs();   
+
+    protected override void OnInitialized()
+    {
+        //EnvironmentSetting.Debug($"SaleInput.OnInitialized開始:");
+        base.OnInitialized();
+    }
+
+    protected override void OnAfterRender(bool firstRender)
+    {
+        //EnvironmentSetting.Debug($"SaleInput.OnAfterRender開始:{firstRender}");
+        base.OnAfterRender(firstRender);
+    }
+
+    protected override async Task OnAfterRenderAsync(bool firstRender)
+    {
+        await slimlock.WaitAsync();
+        EnvironmentSetting.Debug($"SaleInput.OnAfterRenderAsync開始:{firstRender}");
+        await ShowFocus();
+        EnvironmentSetting.Debug($"SaleInput.OnAfterRenderAsync終了:{firstRender}");
+        slimlock.Release();
+    }
+
+    /// <summary>
+    /// フォーカス移動準備
+    /// </summary>
+    /// <param name="row"></param>
+    /// <param name="col"></param>
+    /// <param name="action">EditModeの場合、自動で次のフォーカス移動する</param>
+    private void SetFocus(int row, int col, EditGridFocusEventArgs.ActionType action = EditGridFocusEventArgs.ActionType.Focus)
+    {
+        EnvironmentSetting.Debug($"フォーカス移動準備:開始⇒Row:{row},Col:{col},Action:{action},Enabled:{m_CurrentFocusData.Enabled}");
+        m_CurrentFocusData.Row = row;
+        m_CurrentFocusData.Col = col;
+        m_CurrentFocusData.Action = action; 
+        m_CurrentFocusData.Enabled = true;
+        EnvironmentSetting.Debug($"フォーカス移動準備:完了⇒Row:{row},Col:{col},Action:{action},Enabled:{m_CurrentFocusData.Enabled}");
+    }
+
+    /// <summary>
+    /// OnAfterRenderAsync時フォーカスを設定
+    /// </summary>
+    private async Task<bool> ShowFocus()
+    {
+        try
+        {
+            EnvironmentSetting.Debug($"SaleInput.FocusAsync行Before:Row={m_CurrentFocusData.Row},Col={m_CurrentFocusData.Col},Action={m_CurrentFocusData.Action},Enabled={m_CurrentFocusData.Enabled}");
+            if (!m_CurrentFocusData.Enabled) 
+            {
+                EnvironmentSetting.Debug($"OnAfterRenderAsync⇒return false");
+                return false; 
+            }
+            m_CurrentFocusData.Enabled = false;
+
+            EnvironmentSetting.Debug($"ShowFocus処理:Row={m_CurrentFocusData.Row},Col={m_CurrentFocusData.Col},Action={m_CurrentFocusData.Action},Enabled={m_CurrentFocusData.Enabled}");
+            if (m_CurrentFocusData.Action == EditGridFocusEventArgs.ActionType.Focus && m_CurrentFocusData.Row != -1 && m_CurrentFocusData.Col != -1)
+            {
+                //この時点Grid編集状態ですので、フォーカス可能になる
+                EnvironmentSetting.Debug($"フォーカスへ開始:Row = {m_CurrentFocusData.Row}, Col = {m_CurrentFocusData.Col}");
+                await (Data.SaleList as List<SaleInputRow>)[m_CurrentFocusData.Row].Cells[m_CurrentFocusData.Col].Ref.FocusAsync();  //ここに再度OnAfterRenderAsyncに入るが、EnabledはFalseのため、ShowFocusの動作がしない
+                EnvironmentSetting.Debug($"フォーカスへ完了:Row = {m_CurrentFocusData.Row}, Col = {m_CurrentFocusData.Col}");
+            }
+            return true;
+        }
+        catch(Exception ex)
+        {
+            EnvironmentSetting.Debug(ex.Message);
+            return false;
+        }
+    }
+
+    //protected override async Task OnAfterRenderAsync(bool firstRender)
+    //{
+    //    EnvironmentSetting.Debug($"SaleInput.OnAfterRenderAsync開始:{firstRender}");
+    //    //await ShowFocus();
+    //    //await JSInteropEx.DelGridCol(JSRuntime, "SaleInputTable", 11);
+    //}
+
+    protected override void OnParametersSet()
+    {
+        EnvironmentSetting.Debug($"SaleInput.OnParametersSet開始:");
+        base.OnParametersSet();
+    }
+
+    protected override bool ShouldRender()
+    {
+        EnvironmentSetting.Debug($"SaleInput.ShouldRender開始:");
+        return base.ShouldRender();
+    }
+
+    private async Task KeyPress(int index, SaleInputRow data, KeyboardEventArgs e)
+    {
+        //if (e.Key == "Enter")
+        //{
+        //    List<SaleInputRow> list = (Data.SaleList as List<SaleInputRow>);
+        //    int rowIdx = list.IndexOf(selectedItem1);
+
+        //    // https://bytemeta.vip/repo/MudBlazor/MudBlazor/issues/4192
+        //    // https://github.com/MudBlazor/MudBlazor/issues/3292
+        //    SaleInputRow newitem = (rowIdx == list.Count - 1) ? list[0] : list[rowIdx + 1];
+        //    _table.SetSelectedItem(newitem);
+        //    _table.SetEditingItem(newitem);
+        //    await Task.Delay(50); //画面更新のため
+        //    await newitem.Cells[(int)SaleInputRow.ColType.ItemName].Ref.FocusAsync();  //OnAfterRenderAsyncへ
+        //}
+
+        if (e.Key == "Enter")
+        {
+            try
+            {
+                int rowIdx = GetRowIndex(data);
+                Console.WriteLine($"Row:{rowIdx} Col:{index}");
+                Console.WriteLine("Data:" + CConvert.ToJsonText<SaleInputRow>(data));
+
+                //※その時、Fields[index].Textの値まだ変っていない!!!!!
+                string text = await data.GetInputValue(index, JSRuntime);
+                EnvironmentSetting.Debug($"Return:{index}⇒{text}");
+                keyPressPreventDefault = true;   //イベント中止
+                enterPush = true;   //Enterを押した知らせ
+
+                //通常チェックを行う
+                if (!await IsValid(index, text, data, true)) { return; }
+
+                if (!SetAutoNextFocus(index, true, data)) { return; }
+            }
+            catch (Exception ex)
+            {
+                OperationLog.Instance.WriteLog($"KeyPress:{ex.Message}");
+            }
+            finally
+            {                
+                Refresh("KeyPress");    //UI更新(binding値変更通知)
+            }
+        }
+        else
+        {
+            if (index == (int)SaleInputRow.ColType.PersonCount || index == (int)SaleInputRow.ColType.UnitPrice)
+            {
+                if (CConvert.IsNumPress(e.Key))
+                {
+                    keyPressPreventDefault = false;
+                }
+                else
+                {
+                    keyPressPreventDefault = true; //入力禁止(※:IMEモードで入力したものをここでは通らないため、防げない)
+                }
+            }
+            else
+            {
+                keyPressPreventDefault = false;
+            }
+            enterPush = false;
+        }
+    }
+
+    /// <summary>
+    /// フォーカス移動
+    /// </summary>
+    /// <param name="index">列Index</param>
+    /// <param name="isEnter"></param>
+    /// <returns></returns>
+    private bool SetAutoNextFocus(int index, bool isEnter, SaleInputRow data)
+    {
+        try
+        {
+            int rowIdx = GetRowIndex(data);
+            List<SaleInputRow> list = (Data.SaleList as List<SaleInputRow>);
+            if (isEnter)
+            {
+                if (rowIdx == -1) { return true; }  //削除された場合
+
+                if (index == (int)SaleInputRow.ColType.Page)
+                {
+                    if (rowIdx < (list.Count - 1))
+                    {
+                        //OnAfterRenderAsync:閲覧状態且つ新規行表示⇒編集状態⇒次項目へフォーカス
+                        SetFocus(rowIdx + 1, (int)SaleInputRow.ColType.ItemName);
+                    }
+                }
+                else if (index == (int)SaleInputRow.ColType.DiscountSummary)
+                {
+                    SetFocus(rowIdx, index + 2);
+                }
+                else
+                {
+                    SetFocus(rowIdx, index + 1);
+                }
+            }
+            else
+            {
+                if (index == (int)SaleInputRow.ColType.ItemName)
+                {
+                    if (rowIdx > 0) 
+                    {
+                        SetFocus(rowIdx - 1, (int)SaleInputRow.ColType.ItemName);
+                    }
+                }
+                else if (index == (int)SaleInputRow.ColType.SumDate)
+                {
+                    SetFocus(rowIdx, index - 2);
+                }
+                else
+                {
+                    SetFocus(rowIdx, index - 1);
+                }
+            }
+            return true;
+        }
+        catch
+        {
+            return false;
+        }
+    }
+
+    private void DetailClick(SaleInputRow data)
+    {
+        //Snackbar.Add("詳細表示");
+        List<FeeDtailRow> list = FeeDetailList as List<FeeDtailRow>;
+        list.Clear();
+        list.Add(new() { Name = "本体額", Value = "10,000000" });
+        list.Add(new() { Name = "サービス", Value = "2,000" });
+        list.Add(new() { Name = "消費税", Value = "100" });
+        list.Add(new() { Name = "入湯税", Value = "250" });
+        list.Add(new() { Name = "宿泊税", Value = "400" });
+        list.Add(new() { Name = "合 計", Value = "16,850" });
+
+        List<SaleChildRow> listChild = SaleChildList as List<SaleChildRow>;
+        listChild.Clear();
+        SaleChildRow row = new();
+        row.Cells[0] = "S";
+        row.Cells[1] = "101";
+        row.Cells[2] = "基本料金";
+        listChild.Add(row);
+
+        row = new();
+        row.Cells[0] = "S";
+        row.Cells[1] = "101";
+        row.Cells[2] = "朝食";
+        listChild.Add(row);
+
+        data.ActiveCol = (int)SaleInputRow.ColType.Detail;
+        data.ShowDetails = !data.ShowDetails;
+    }
+
+    private void OnCommitEditButtonClicked(MouseEventArgs e)
+    {
+        _table.RowEditCommit?.Invoke(_table.SelectedItem);
+        _table.OnCommitEditClick.InvokeAsync(e);
+        _table.SetSelectedItem(null);
+    }
+
+    private async Task Save()
+    {
+        (Data.SaleList as List<SaleInputRow>).Add(new());
+        //SaleInputRow newitem = (Data.SaleList as List<SaleInputRow>)[5];
+        ////await Task.Delay(50);
+        //_table.SetSelectedItem(newitem);
+        //_table.SetEditingItem(newitem);
+        await Task.Delay(50);
+        //await newitem.Cells[(int)SaleInputRow.ColType.ItemName].Ref.FocusAsync();
+    }
+
+    private async Task KeyDown(int index, SaleInputRow data, KeyboardEventArgs e)
+    {
+        if (e.Key == "ArrowUp")
+        {
+            try
+            {
+                EnvironmentSetting.Debug($"ArrowUp:{index}");
+                if (SetAutoNextFocus(index, false, data))
+                {
+                    //BlazorのBugでEnterのパラメータ変数できない!
+                    //Uncaught Error: System.ArgumentException: There is no event handler associated with this event. EventId: '290'. (Parameter 'eventHandlerId')
+                    //mkArtakMSFT modified the milestones: Next sprint planning, 6.0-preview4 on 20 Mar ← Net6.0-preview4対応だそう
+                    keyDownPreventDefault = true;
+                    arrowUpPush = true;
+                }
+                else
+                {
+                    keyDownPreventDefault = false;
+                    arrowUpPush = false;
+                }
+            }
+            catch (Exception ex)
+            {
+                OperationLog.Instance.WriteLog($"KeyDown:{ex.Message}");
+            }
+            finally
+            {
+                Refresh("KeyDown⇒↑");    //UI更新(binding値変更通知)
+            }
+        }
+        else if (e.Key == "End")
+        {
+            if (data.Cells[index].ShowStyle == EShowStyle.ShowList)
+            {
+                data.ActiveCol = index;
+                if (index == (int)SaleInputRow.ColType.SumDate)
+                {
+                    var parameters = new DialogParameters { ["Title"] = $"集計日選択", ["Data"] = CConvert.ToDateTime(data.Cells[index].Text) };
+                    var dialog = DialogService.Show<SelectDate>(string.Empty, parameters);
+                    var ret = await dialog.Result;
+                    if (!ret.Cancelled)
+                    {
+                        EnvironmentSetting.Debug(ret.Data.ToString());
+                        data.Cells[index].Text = ret.Data.ToString();
+                        //StateHasChanged();
+                    }
+                }
+                else
+                {
+                    data.ShowDetails = !data.ShowDetails;
+                }
+            }
+        }
+        else if (e.Key == "Delete")
+        {
+            if (index == (int)SaleInputRow.ColType.ItemName)
+            {
+                int rowIdx = GetRowIndex(data);
+                List<SaleInputRow> list = (Data.SaleList as List<SaleInputRow>);
+                bool isLastRow = rowIdx == (list.Count - 1);
+                if (isLastRow) { return; }
+                SetFocus(rowIdx, (int)SaleInputRow.ColType.ItemName);
+                EnvironmentSetting.Debug($"削除前件数:{list.Count}");
+                list.Remove(data);
+                EnvironmentSetting.Debug($"削除後件数:{list.Count}");
+                keyDownPreventDefault = false;
+                arrowUpPush = false;
+            }
+        }
+        else
+        {
+            keyDownPreventDefault = false;
+            arrowUpPush = false;
+        }
+
+    }
+
+    private async Task Enter(int index, SaleInputRow data, FocusEventArgs e)
+    {
+        await slimlock.WaitAsync();
+        int rowIdx = GetRowIndex(data);
+        Console.WriteLine($"Enter⇒Row:{rowIdx} Col:{index}");
+        slimlock.Release();
+        //ここは必ずUI更新
+    }
+
+    private async Task Leave(int index, SaleInputRow data, FocusEventArgs e)
+    {
+        string text = string.Empty;
+        try
+        {
+            await slimlock.WaitAsync();
+            Console.WriteLine($"Leave⇒Start");
+            int rowIdx = GetRowIndex(data);
+            text = data.GetCellText(index);
+            Console.WriteLine($"Leave⇒Row:{rowIdx} Col:{index} enterPush:{enterPush}, text:{text}");
+
+            if (enterPush)
+            {
+                //Enterキーを押した時にも既にチェック済
+                enterPush = false;
+            }
+            else
+            {
+                //値変更したら、イベント発生
+                if (!data.IsValueChanged(index, text))
+                {
+                    //必須判断:初期表示時:OrgTextは空白のため、値変更しないまま
+                    return;
+                }
+
+                //通常チェックを行う
+                if (!await IsValid(index, text, data, false))
+                {
+                    return;
+                }
+
+                //Refresh("Leave(変更あり)");    //UI更新(binding値変更通知)
+            }
+        }
+        catch (Exception ex)
+        {
+            OperationLog.Instance.WriteLog($"Leave:{ex.Message}");
+        }
+        finally
+        {
+            //Refresh();    //UI更新(binding値変更通知)
+            Console.WriteLine($"Leave⇒End");
+            slimlock.Release();
+
+            //ここは必ずUI更新
+        }
+    }
+
+    private int GetRowIndex(SaleInputRow data)
+    {
+        return (Data.SaleList as List<SaleInputRow>).IndexOf(data);
+    }
+
+    /// <summary>
+    /// 業務チェック処理
+    /// </summary>
+    /// <param name="index"></param>
+    /// <param name="inputText"></param>
+    /// <param name="data"></param>
+    /// <param name="isEnter"></param>
+    /// <returns></returns>
+    private async Task<bool> IsValid(int index, string inputText, SaleInputRow data, bool isEnter)
+    {
+        int rowIdx = GetRowIndex(data);
+        //最終行判断
+        List<SaleInputRow> list = (Data.SaleList as List<SaleInputRow>);
+        bool isLastRow = rowIdx == (list.Count - 1);
+
+        if (index == (int)SaleInputRow.ColType.ItemName)
+        {
+            if (!await IsValidItemName(rowIdx, inputText, data, isEnter, isLastRow, true))
+            {
+                return false;
+            }
+        }
+        else if(index == (int)SaleInputRow.ColType.SumDate)
+        {
+        }
+        else
+        {
+
+        }
+        return true;
+    }
+
+    
+
+    private RenderFragment RenderWidget(string msg) => builder =>
+    {
+        builder.OpenComponent(0, typeof(MessageContext));
+        builder.AddAttribute(1, "Text", msg);
+        builder.CloseComponent();
+    };
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="inputText"></param>
+    /// <param name="data"></param>
+    /// <param name="isEnter"></param>
+    /// <param name="isLastRow">Trueの場合、必ずID</param>
+    /// <param name="isAny">True:ID or Name  False:ID</param>
+    /// <returns></returns>
+    private async Task<bool> IsValidItemName(int rowIdx, string inputText, SaleInputRow data, bool isEnter, bool isLastRow, bool isAny)
+    {
+        if (inputText.Trim().Length == 0) { return true; }
+        HotelPms.Data.UseInfo.Sale curSale = data.GetSale();
+        bool nameChanged = false;
+
+        if (isLastRow)
+        {
+            if (!CanCreateSale()) { return true; }
+        }
+        else
+        {
+            //変更されたかどうか
+            bool isChanged = false;
+            if (isAny)
+            {
+                //直接入力する(数字の場合、ItemIDで扱う)
+                if (CConvert.IsWholeNumber(inputText))
+                {
+                    if (curSale.IsReadOnly()) { return true; }
+                    if (inputText.PadLeft(50, '0') != curSale.ItemID.PadLeft(50, '0')) { isChanged = true; } else { data.RestoreText(SaleInputRow.ColType.ItemName); }
+                }
+                else
+                {
+                    if (inputText != curSale.ItemName) { isChanged = true; nameChanged = true; }
+                }
+            }
+            else
+            {
+                //Endキーより別の科目を選択など
+                if (inputText != curSale.ItemID) { isChanged = true; }
+            }
+            if (!isChanged) { return true; }  //変更しなかったら
+        }
+
+        if (!RaiseValueChanged((int)SaleInputRow.ColType.ItemName, data)) { return false; }   //変更イベント通知
+
+        //名称変更のみ
+        if (nameChanged)
+        {
+            data.SetDataField((int)SaleInputRow.ColType.ItemName, inputText);
+            return true;
+        }
+
+        //入力値はItemIDと処理する
+        HotelPms.Data.Master.Item item = await MasterCore.GetItem(inputText);
+        if (item == null)
+        {
+            //科目が存在しない
+            if (isEnter) { Message.Show(RenderMessage(inputText)); }
+            data.RestoreText(SaleInputRow.ColType.ItemName);
+            return false;
+        }
+
+        if (isLastRow)
+        {            
+            int saleID = await EnvironmentSetting.GetSeq(ESeqType.Sale);
+            int taxRate = await EnvironmentSetting.GetTaxRate(Data.SelUseRoomRow.UseRoom.UseDate.ToText(), item.TaxType);
+            curSale = Data.SelUseRoomRow.UseRoom.AddSaleByItem(saleID, taxRate, item);  //選択された部屋より追加            
+            data.DataList[rowIdx] = curSale;    
+        }
+        else
+        {
+            //既存行の科目変更
+            if (curSale.ItemKind == (int)EItemKind.StayBase || curSale.ItemKind == (int)EItemKind.DayUseBase)
+            {
+                if (item.Kind != (int)EItemKind.StayBase && item.Kind != (int)EItemKind.DayUseBase)
+                {
+                    if (isEnter) { Message.Show(RenderMessage("基本科目を入力してください。")); }
+                    data.RestoreText(SaleInputRow.ColType.ItemName);
+                    return false;
+                }
+            }
+            else
+            {
+                if (item.Kind == (int)EItemKind.StayBase || item.Kind == (int)EItemKind.DayUseBase)
+                {
+                    if (isEnter) { Message.Show(RenderMessage("追加科目を入力してください。")); }
+                    data.RestoreText(SaleInputRow.ColType.ItemName);
+                    return false;
+                }
+            }
+
+            HotelPms.Data.UseInfo.UseRoom useRoom;
+            HotelPms.Data.UseInfo.Sale newSale;            
+            if (Data.SaleDispType == ESaleDispType.Normal)
+            {
+                useRoom = curSale.Parent as HotelPms.Data.UseInfo.UseRoom;
+                useRoom.RemoveSale(curSale);
+                int saleID = await EnvironmentSetting.GetSeq(ESeqType.Sale);
+                int taxRate = await EnvironmentSetting.GetTaxRate(useRoom.UseDate.ToText(), item.TaxType);
+                newSale = useRoom.AddSaleByItem(saleID, taxRate, item, curSale);
+                data.DataList.Clear();
+                data.DataList.Add(newSale);
+            }
+            else
+            {
+                //まとめモードの変更
+                List<HotelPms.Data.UseInfo.Sale> copyList = new List<HotelPms.Data.UseInfo.Sale>();
+                copyList.AddRange(data.DataList);
+                foreach (HotelPms.Data.UseInfo.Sale tagSlip in copyList)
+                {
+                    curSale = tagSlip as HotelPms.Data.UseInfo.Sale;
+                    useRoom = curSale.Parent as HotelPms.Data.UseInfo.UseRoom;
+                    useRoom.RemoveSale(curSale);      //元の伝票を削除
+                    int saleID = await EnvironmentSetting.GetSeq(ESeqType.Sale);
+                    int taxRate = await EnvironmentSetting.GetTaxRate(useRoom.UseDate.ToText(), item.TaxType);
+                    newSale = useRoom.AddSaleByItem(saleID, taxRate, item, curSale); //新伝票の追加                                                                    
+                    int orgSlipIndex = data.DataList.IndexOf(curSale);  
+                    data.DataList[orgSlipIndex] = newSale;   //切替える
+                }
+            }
+        }
+
+
+        data.SetDataField((int)SaleInputRow.ColType.ItemName, item.Name);
+
+        //画面表示(イベントを起こすため、必ず一番最後)
+        data.Cells[(int)SaleInputRow.ColType.ItemName].Text = item.Name;
+
+        //新規行追加
+        if (isLastRow) 
+        {
+            //OnAfterRenderAsync:閲覧状態且つ新規行表示⇒編集状態⇒次項目へフォーカス
+            SetFocus(rowIdx, (int)SaleInputRow.ColType.PersonCount);
+            EnvironmentSetting.Debug($"新規行追加⇒開始");
+            (Data.SaleList as List<SaleInputRow>).Add(new());
+            EnvironmentSetting.Debug($"新規行追加⇒終了");
+            return false;  //次の列SetAutoNextFocus行かない
+        }
+        return true;
+    }
+
+    /// <summary>
+    /// 新規伝票可能かどうか
+    /// </summary>
+    /// <returns></returns>
+    private bool CanCreateSale()
+    {
+        return true;
+    }
+
+    /// <summary>
+    /// 値変更
+    /// </summary>
+    public bool RaiseValueChanged(int index, SaleInputRow data)
+    {
+        return true;
+    }
+
+    /// <summary>
+    /// コントロール再表示
+    /// </summary>
+    public void Refresh(string type)
+    {
+        EnvironmentSetting.Debug($"再表示へ開始:{type}");
+        StateHasChanged();
+        EnvironmentSetting.Debug($"再表示へ終了:{type}");
+        //await InvokeAsync(StateHasChanged);
+        //OnRefresh?.Invoke(); 
+    }
+}

--
Gitblit v1.10.0